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
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 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
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 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
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 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 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 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
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 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
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 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
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
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 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
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