def reorderList(self, head: ListNode) -> None:
     """Do not return anything, modify head in-place instead.
 """
     s = ListNode('')
     s.next = head
     # step 1: reverse the 2nd half of the linked list: 1->2->3->4->5 to 1->2->3<-4<-5
     x = y = s
     while y:
         x = x.next
         y = y.next
         if y:
             y = y.next
     # x is the middle one, reverse from x to ende
     prev, curr = None, x
     while curr:
         hold = curr.next
         curr.next = prev
         prev = curr
         curr = hold
     # step 2: two pointers from init and ende to switch 1(x)->2->3<-4<-5(y) to 1->5->2(x)->3<-4(y) to 1->5->2->4->3
     x, y = head, prev
     while not (x == y or x.next == y):
         # hold of x.next and y.next
         u, v = x.next, y.next
         x.next = y
         y.next = u
         x, y = u, v
     return None
 def deleteNode(self, node: ListNode) -> None:
     """Do not return anything, modify node in-place instead.
   Key: O(1), move the value of node.next, and link from node to node.next.next.
   The key is since we don't have prev, we modify this node as prev and instead delete node.next as node.
 """
     node.val = node.next.val
     node.next = node.next.next
 def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
     if m == n: return head
     s = ListNode('')
     s.next = head
     i = 0
     x = y = z = s
     while i < m - 1:
         x = x.next
         y = y.next
         z = z.next
         i += 1
     y = y.next
     z = z.next
     i += 1
     p = x
     while i < n:
         q = z.next
         z.next = p
         p = z
         z = q
         i += 1
     x.next = z
     y.next = z.next
     z.next = p
     return s.next
 def rotateRight(self, head: ListNode, k: int) -> ListNode:
     """Two pointers.
 """
     s = ListNode(0)
     s.next = head
     if not s.next:
         return s.next
     x, y, i = s, s, 0
     while i < k:
         if y.next:
             y = y.next
         else:
             y = s.next
             k %= i
             if k == 0:
                 k += i * 2
             else:
                 k += i
         i += 1
     while y.next:
         x = x.next
         y = y.next
     if not x == s:
         y.next = s.next
         s.next = x.next
         x.next = None
     return s.next
Exemple #5
0
 def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
     """Q0002
 """
     # parse list to str
     x1 = self._parse(l1)
     x2 = self._parse(l2)
     # add over strs
     n1 = len(x1)
     n2 = len(x2)
     # zip truncation
     if n1 < n2:
         x1 = "0" * (n2 - n1) + x1
     else:
         x2 = "0" * (n1 - n2) + x2
     # add over strs
     s = ListNode('')
     k, node = 0, s
     for i1, i2 in zip(x1[::-1], x2[::-1]):
         v = k + int(i1) + int(i2)
         k = v // 10
         v %= 10
         node.prev = ListNode(v)
         node.prev.next = node
         node = node.prev
     if k:
         node.prev = ListNode(k)
         node.prev.next = node
         node = node.prev
     # sentinel
     if node == s:
         node = None
     else:
         s.prev.next = None
     return node
Exemple #6
0
 def removeZeroSumSublists(self, head: ListNode) -> ListNode:
   # linked list -> array
   node, nums = head, []
   while node:
     nums.append(node.val)
     node = node.next
   # consecutive sum 0 <=> prefix sum seen
   prefix, seen, remove = list(accumulate(nums)), {}, set()
   for i, x in enumerate(prefix):
     if x == 0:
       for k in range(i + 1):
         remove.add(k)
     elif x in seen and seen[x] not in remove:
       for k in range(seen[x] + 1, i + 1):
         remove.add(k)
     else:
       seen[x] = i
   ans = [nums[i] for i in range(len(nums)) if i not in remove]
   # array -> linked list
   s = prev = ListNode('')
   for x in ans:
     curr = ListNode(x)
     prev.next = curr
     prev = curr
   return s.next
 def deleteNode(self, node: ListNode) -> None:
     """Do not return anything, modify node in-place instead.
   Key: O(N), move the value one by one while traverse from node to tail.
 """
     while node.next.next:
         node.val = node.next.val
         node = node.next
     node.val = node.next.val
     node.next = None
Exemple #8
0
 def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
     s = l = ListNode(0)
     while l1 and l2:
         if l1.val <= l2.val:
             l.next = ListNode(l1.val)
             l1 = l1.next
         else:
             l.next = ListNode(l2.val)
             l2 = l2.next
         l = l.next
     l.next = l1 or l2
     return s.next
 def deleteDuplicates(self, head: ListNode) -> ListNode:
   s = ListNode('')
   s.next = head
   x = y = s
   while y and y.next:
     while y.next and y.val == y.next.val:
       y = y.next  
     y = y.next
     if (not y) or (not y.next) or (not y.val == y.next.val):
       x.next = y
       x = x.next
   return s.next
 def deleteDuplicates(self, head: ListNode) -> ListNode:
     s = ListNode(0)
     s.next = head
     x = y = head
     while y and y.next:
         y = y.next
         if x.val < y.val:
             x.next = y
             x = x.next
     if x and x.next:
         x.next = None
     return s.next
Exemple #11
0
 def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
     s = ListNode(0)
     s.next = head
     x = s
     z = s
     for i in range(n):
         x = x.next
     while x.next:
         x = x.next
         z = z.next
     z.next = z.next.next
     return s.next
Exemple #12
0
 def removeElements(self, head: ListNode, val: int) -> ListNode:
     s = ListNode('')
     s.next = head
     prev, node = s, head
     while node:
         if node.val == val:
             # skip node, hold prev
             prev.next = node.next
         else:
             # move prev to forward
             prev = node
         node = node.next
     return s.next
Exemple #13
0
 def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
   n = s = ListNode(0)
   k = 0
   while l1 or l2 or k > 0:
     if l1:
       k += l1.val
       l1 = l1.next
     if l2:
       k += l2.val
       l2 = l2.next
     n.next = ListNode(k % 10)
     k //= 10
     n = n.next
   return s.next
 def partition(self, head: ListNode, x: int) -> ListNode:
     p = l = ListNode('')
     q = g = ListNode('')
     z = head
     while z:
         if z.val < x:
             l.next = z
             l = l.next
         else:
             g.next = z
             g = g.next
         z = z.next
     l.next = q.next
     g.next = None
     return p.next
 def reverseList(self, head: ListNode) -> ListNode:
     """Iterative Solver 1.
 """
     s = ListNode(0)
     s.next = head
     if s.next and s.next.next:
         x = s.next
         y = s.next.next
         while y:
             h = s.next
             z = y.next
             s.next = y
             y.next = h
             x.next = z
             y = x.next
     return s.next
Exemple #16
0
 def sortList(self, head: ListNode) -> ListNode:
     """merge sort on linked list.
   iterate over linked list, say, s -> head -> ...-> ..
   k: number of every k nodes are sorted, k = 1, 2, .. n, e.g., s -> l -> .. -> x -> .. -> y -> .. -> r -> .. 
                                                                               ---------  ---------
                                                                                k nodes    k nodes
   merge k nodes from x and y, so every 2k nodes are sorted, l and r are the left and right node for next x, y pair
 """
     s = ListNode('')
     s.next = head
     # linked list length
     # it is ok to get n from k = 1 case, but this way is more cleaner
     x, n = s, 0
     while x.next:
         x = x.next
         n += 1
     # merge sort
     k = 1
     while k < n:
         l = s
         while l.next:
             x = l.next
             # move k step forward, break link so x -> ... -> None, with lengh k
             y = x
             for _ in range(k - 1):
                 if y is not None:
                     y = y.next
             if y is not None:
                 h = y
                 y = y.next
                 h.next = None
             # move k step forward, break link so y -> ... -> None, with lengh k
             r = y
             for _ in range(k - 1):
                 if r is not None:
                     r = r.next
             if r is not None:
                 h = r
                 r = r.next
                 h.next = None
             # merge and connect, so that l -> mergeSorted(x, y) -> r
             if y is not None and not x == y:
                 l = self.merge(l, x, y, r)
             else:
                 break
         k *= 2
     return s.next
 def oddEvenList(self, head: ListNode) -> ListNode:
     """TC: O(N), SC: O(1).
 """
     # sentinel head for odd and even
     so, se = ListNode(''), ListNode('')
     xo, xe = so, se
     while head:
         xo.next = head
         xo = xo.next
         if head.next:
             head = head.next
             xe.next = head
             xe = xe.next
         head = head.next
     xo.next = se.next
     xe.next = None
     return so.next
Exemple #18
0
 def plusOne(self, head: ListNode) -> ListNode:
   # sentinel node
   s = ListNode('')
   s.next = head
   # create prev along the way
   node = s
   while node.next:
     node.next.prev = node
     node = node.next
   # plus one on the node from tail
   while True:
     if node.val < 9:
       node.val += 1
       break
     else:
       node.val = 0
       node = node.prev
       if node.val == '':
         x = ListNode(1)
         x.next = node.next
         node.next.prev = x
         node.next = x
         x.prev = node
         break
   return s.next
 def reverseList(self, head: ListNode) -> ListNode:
     """Recursive Solver.
 """
     if head and head.next:
         x = self.reverseList(head.next)
         head.next.next = head
         head.next = None
         return x
     else:
         return head
 def deleteNodes(self, head: ListNode, m: int, n: int) -> ListNode:
     s = ListNode('')
     s.next = head
     prev, node = s, head
     while node:
         count = 0
         while node and count < m:
             prev, node = node, node.next
             count += 1
         hold = prev
         if count == m:
             count = 0
             while node and count < n:
                 prev, node = node, node.next
                 count += 1
         prev = hold
         # passthrough
         prev.next = node
     return s.next
Exemple #21
0
 def insertionSortList(self, head: ListNode) -> ListNode:
     # INTEGER_MIN
     s = ListNode(-2147483648)
     s.next = head
     # insertion sort
     x = head
     while x and x.next:
         y = x.next
         if y.val < x.val:
             z = s
             while not z == x:
                 if y.val < z.next.val:
                     x.next = y.next
                     y.next = z.next
                     z.next = y
                     break
                 z = z.next
         else:
             x = x.next
     return s.next
Exemple #22
0
 def isPalindrome(self, head: ListNode) -> bool:
     """Two pass, 1st reach to tail and create reverse link along the way, 2nd two pointers head and tail.
   An alternative approach is 1st pass two pointers slow (1 step each iteration) and fast (2 step each iteration),
   and when fast reach to the tail, slow reach to middle, then reverse along the way slow from middle to the tail,
   and then 2nd pass two pointers head and tail and comparison along the way. 
   However, this alternative approach need more caution on corner cases, odd/even middle, empty linked list and etc.
 """
     # 1st pass
     s = ListNode('')
     s.next = head
     prev, node = s, head
     while node:
         node.prev = prev
         prev = node
         node = node.next
     t = ListNode('')
     prev.next = t
     t.prev = prev
     # 2nd pass
     x, y = s.next, t.prev
     # equality test use x is y (kind like x === y in javascript) instead of x == y, strict for reference equality,
     # because in the config.listnode, class ListNode defined __eq__() as value equal for general purpose equality.
     while not (x is y or x.prev is y):
         if not x.val == y.val:
             return False
         else:
             x = x.next
             y = y.prev
     return True
 def mergeKLists(self, lists: List[ListNode]) -> ListNode:
     k = len(lists)
     h = [l for l in lists if l]
     heapq.heapify(h)
     s = ListNode(0)
     x = s
     while h:
         v = heapq.heappop(h)
         x.next = v
         x = x.next
         if v.next:
             heapq.heappush(h, v.next)
     return s.next
 def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
     """Keep Two Pairs, prev and curr, prev group tail and curr group head.
 """
     s = prevK = ListNode(0)
     s.next = holdK = currK = head
     i = 1
     while currK:
         currK = currK.next
         if i % k == 0:
             prev, curr = currK, holdK
             for _ in range(k):
                 curr.next, curr, prev = prev, curr.next, curr
             prevK.next, prevK, holdK = prev, holdK, currK
         i += 1
     return s.next
Exemple #25
0
 def removeZeroSumSublists(self, head: ListNode) -> ListNode:
   # O(N), one pass, in-place
   # s: sentinel node
   s = node = ListNode(0)
   s.next = head
   # consecutive sum 0 <=> prefix sum seen
   prefix, seen = 0, OrderedDict()
   while node:
     prefix += node.val
     prev = seen.get(prefix, node)
     while prefix in seen:
       seen.popitem()
     seen[prefix] = prev
     prev.next = node.next
     node = node.next
   return s.next
Exemple #26
0
 def swapPairs(self, head: ListNode) -> ListNode:
     s = ListNode(0)
     s.next = head
     x = s
     while x.next and x.next.next:
         z = ListNode(x.next.val)
         x.next = x.next.next
         x = x.next
         z.next = x.next
         x.next = z
         x = x.next
     return s.next