while p.next: length += 1 p = p.next k = length - k % length if k == length: # corner case return head p.next = head # circle the list # move length - k steps for break point while k > 0: k -= 1 p = p.next ans_head = p.next p.next = None return ans_head # TESTS tests = [ ([], 4, []), ([1, 2, 3], 0, [1, 2, 3]), ([1, 2], 2, [1, 2]), ([1], 99, [1]), ([1, 2, 3, 4, 5], 2, [4, 5, 1, 2, 3]), ([0, 1, 2], 4, [2, 0, 1]), ] for array, k, expected in tests: sol = Solution() actual = ListNode.to_array(sol.rotateRight(ListNode.from_array(array), k)) print("Rotate", array, "right by", k, "places ->", actual) assert actual == expected
class Solution: def insertionSortList(self, head: ListNode) -> ListNode: prev = sentinal = ListNode() while head: nxt = head.next # Optimization: search from begining # only when head is supposed in front of last insert point if head.val <= prev.val: prev = sentinal while prev.next and prev.next.val < head.val: prev = prev.next head.next = prev.next prev.next = head head = nxt return sentinal.next # TESTS for array, expected in [ ([], []), ([3], [3]), ([4, 2, 1, 3], [1, 2, 3, 4]), ([-1, 5, 3, 4, 0], [-1, 0, 3, 4, 5]), ]: sol = Solution() actual = ListNode.to_array( sol.insertionSortList(ListNode.from_array(array))) print("Sort", array, "->", actual) assert actual == expected
return head dummy = ListNode(0, head) pre, i = dummy, 0 while i < left - 1: i, pre = i + 1, pre.next start = pre.next then = start.next while i < right - 1: start.next = then.next then.next = pre.next pre.next = then then = start.next i += 1 return dummy.next # TESTS for array, left, right, expected in [ ([1, 2, 3, 4, 5], 2, 4, [1, 4, 3, 2, 5]), ([5], 1, 1, [5]), ]: sol = Solution() actual = ListNode.to_array( sol.reverseBetween(ListNode.from_array(array), left, right)) print("Reverse", array, "between", left, "and", right, "->", actual) assert actual == expected
prev.next = p.next q = p.next.next p.next.next, p.next = p, q prev, p = p, q return dummy.next def swapPairsRec(self, head: ListNode) -> ListNode: if not head or not head.next: return head n = head.next head.next = self.swapPairsRec(n.next) n.next = head return n # TESTS for t, expected in [ ([], []), ([1], [1]), ([1, 2], [2, 1]), ([1, 2, 3], [2, 1, 3]), ([1, 2, 3, 4], [2, 1, 4, 3]), ([1, 2, 3, 4, 5, 6, 7], [2, 1, 4, 3, 6, 5, 7]), ([1, 2, 3, 4, 5, 6, 7, 8], [2, 1, 4, 3, 6, 5, 8, 7]), ]: sol = Solution() actual = ListNode.to_array(sol.swapPairs(ListNode.from_array(t))) print("Swap pairs", t, "->", actual) assert actual == expected assert expected == ListNode.to_array(sol.swapPairsRec(ListNode.from_array(t)))
dummy, carry = ListNode(), 0 for e1, e2 in zip_longest(s1[::-1], s2[::-1]): s = carry if e1: s += e1 if e2: s += e2 carry = s // 10 dummy.next = ListNode(s % 10, dummy.next) if carry == 1: dummy.next = ListNode(1, dummy.next) return dummy.next # TESTS for a1, a2, expected in [ ([], [], []), ([1], [], [1]), ([3], [5], [8]), ([6], [9], [1, 5]), ([6, 5], [9, 0, 2], [9, 6, 7]), ([6, 5], [9, 4, 9], [1, 0, 1, 4]), ([7, 2, 4, 3], [5, 6, 4], [7, 8, 0, 7]), ([9, 9, 9], [1], [1, 0, 0, 0]), ]: sol = Solution() actual = ListNode.to_array( sol.addTwoNumbers(ListNode.from_array(a1), ListNode.from_array(a2))) print("Add", a1, "+", a2, "->", actual) assert actual == expected
# produce two sub lists and concatnate them def oddEvenListV2(self, head: ListNode) -> ListNode: if not head: return None pod, pev, evhead = head, head.next, head.next while pod.next and pev.next: pod.next = pev.next pev.next = pod.next.next pod = pod.next pev = pev.next pod.next = evhead return head # TESTS tests = [ ([], []), ([1], [1]), ([1, 2], [1, 2]), ([1, 2, 3, 4, 5], [1, 3, 5, 2, 4]), ([1, 2, 3, 4, 5, 6], [1, 3, 5, 2, 4, 6]), ([2, 1, 3, 5, 6, 4, 7], [2, 3, 6, 7, 1, 5, 4]), ] for t in tests: sol = Solution() actual1 = ListNode.to_array(sol.oddEvenListV1(ListNode.from_array(t[0]))) actual2 = ListNode.to_array(sol.oddEvenListV2(ListNode.from_array(t[0]))) print("Odd even linked list of", t[0], "->", t[1]) assert actual1 == t[1] and actual2 == t[1]
if not head or not head.next: return head pre, slow, fast = None, head, head while fast and fast.next: pre, slow, fast = slow, slow.next, fast.next.next pre.next = None return self.merge(self.sortList(head), self.sortList(slow)) def merge(self, l1: ListNode, l2: ListNode) -> ListNode: sentinal = p = ListNode() while l1 and l2: if l1.val <= l2.val: p.next, p, l1 = l1, l1, l1.next else: p.next, p, l2 = l2, l2, l2.next p.next = l1 or l2 return sentinal.next # TESTS tests = [ ([4, 2, 1, 3], [1, 2, 3, 4]), ([-1, 5, 3, 4, 0], [-1, 0, 3, 4, 5]), ([], []), ([7], [7]), ] for nums, expected in tests: sol = Solution() actual = ListNode.to_array(sol.sortList(ListNode.from_array(nums))) assert actual == expected
class Solution: def reverseKGroup(self, head: ListNode, k: int) -> ListNode: dummy = jump = ListNode(0) dummy.next = l = r = head while True: count = 0 while r and count < k: # use r to locate the range r, count = r.next, count + 1 if count == k: cur, pre = l, r for _ in range(k): cur.next, cur, pre = pre, cur.next, cur jump.next, jump, l = pre, l, r # connect two k-groups else: return dummy.next # TESTS for array, k, expected in [ ([1, 2, 3, 4, 5], 2, [2, 1, 4, 3, 5]), ([1, 2, 3, 4, 5], 3, [3, 2, 1, 4, 5]), ([1, 2, 3, 4, 5], 1, [1, 2, 3, 4, 5]), ([1], 1, [1]), ]: sol = Solution() actual = ListNode.to_array(sol.reverseKGroup(ListNode.from_array(array), k)) print("Reverse nodes in k-group", array, "->", actual) assert actual == expected
class Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: sentinel = ListNode(0) p = sentinel while l1 and l2: if l1.val < l2.val: p.next = l1 l1 = l1.next else: p.next = l2 l2 = l2.next p = p.next p.next = l1 if l1 else l2 return sentinel.next # TESTS for l1, l2, expected in [ ([], [], []), ([1], [2], [1, 2]), ([], [0], [0]), ([1, 1, 1], [1, 1, 2], [1, 1, 1, 1, 1, 2]), ([1, 2, 4], [1, 3, 4], [1, 1, 2, 3, 4, 4]), ([1, 3, 9], [2, 4, 6, 8, 10], [1, 2, 3, 4, 6, 8, 9, 10]), ]: sol = Solution() actual = ListNode.to_array( sol.mergeTwoLists(ListNode.from_array(l1), ListNode.from_array(l2))) print("Merge", l1, "and", l2, "->", actual) assert actual == expected
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: def removeElements(self, head: ListNode, val: int) -> ListNode: sentinel = ListNode(val + 1, head) p = sentinel while p and p.next: if p.next.val == val: p.next = p.next.next else: p = p.next return sentinel.next # TESTS tests = [ ([], 1, []), ([1], 2, [1]), ([1, 1], 1, []), ([6, 1, 2, 3, 6, 4, 5, 6], 6, [1, 2, 3, 4, 5]), ] for t in tests: sol = Solution() actual = sol.removeElements(ListNode.from_array(t[0]), t[1]) print("Remove elements from", t[0], "->", ListNode.to_array(actual))
from local_packages.list import ListNode class Solution: def partition(self, head: ListNode, x: int) -> ListNode: p1 = h1 = ListNode(-101) p2 = h2 = ListNode(101) while head: if head.val < x: p1.next = head p1 = p1.next else: p2.next = head p2 = p2.next head = head.next p1.next, p2.next = h2.next, None return h1.next # TESTS for array, x, expected in [ ([], 3, []), ([1, 4, 3, 2, 5, 2], 3, [1, 2, 2, 4, 3, 5]), ([2, 1], 2, [1, 2]), ([1, 4, 3, 0, 2, 5, 2], 3, [1, 0, 2, 2, 4, 3, 5]), ]: sol = Solution() actual = ListNode.to_array(sol.partition(ListNode.from_array(array), x)) print("Partition", array, "->", actual) assert actual == expected
def deleteDuplicates(self, head: ListNode) -> ListNode: sentinal = ListNode(0, next=head) p, was_dup = sentinal, False while p and p.next: if p.next.next: is_dup = p.next.val == p.next.next.val if is_dup or was_dup: p.next = p.next.next # delete p.next but not iterate else: p = p.next was_dup = is_dup else: if was_dup: p.next = None # delete the last duplicate p = p.next return sentinal.next # TESTS for given, expected in [ ([], []), ([1, 2, 3, 3, 4, 4, 5], [1, 2, 5]), ([1, 1, 1, 2, 3], [2, 3]), ([1, 4, 4, 4], [1]), ]: sol = Solution() actual = ListNode.to_array(sol.deleteDuplicates( ListNode.from_array(given))) print("Delete duplicates from", given, "->", actual) assert actual == expected
while first and first.next: first, second = first.next.next, second.next mid, p = second.next, second.next second.next = None # Reverse the second half while p and p.next: nxt = p.next p.next = nxt.next nxt.next = mid mid = nxt # Interweave p1, p2 = head, mid while p1 and p2: p1nxt, p2nxt = p1.next, p2.next p1.next, p2.next = p2, p1nxt p1, p2 = p1nxt, p2nxt # TEST tests = [ ([1, 2, 3, 4], [1, 4, 2, 3]), ([1, 2, 3, 4, 5], [1, 5, 2, 4, 3]), ([0, 1, 2, 3, 4, 5], [0, 5, 1, 4, 2, 3]), ] for t in tests: sol = Solution() head = ListNode.from_array(t[0]) sol.reorderList(head) print("Reorder list ->", ListNode.to_array(head)) assert ListNode.to_array(head) == t[1]