Top-down merge sort linked list
Problem¶
Implement recursive merge sort for a linked list.
Key trick¶
Recursively split the input into halves, then stably merge the sorted halves.
Trap¶
Choose from the left on equality for stability; linked lists also use \(O(\log n)\) recursion space.
Why is it interesting?¶
It guarantees stable \(O(n \log n)\) sorting and works especially well with linked lists.
Python solution¶
class sorting_merge_sort_top_down_linked_list:
def sort(
self,
head: ListNode | None,
) -> ListNode | None:
# Empty and one-node lists are already sorted.
if head is None or head.next is None:
return head
# Find the midpoint with the slow/fast-pointer pattern.
# Starting `fast` one node ahead leaves `slow` at the end
# of the left half.
slow = head
fast = head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# Split the list into two independent lists.
r = slow.next
slow.next = None
# Sort each half and merge their nodes.
l = self.sort(head)
r = self.sort(r)
return self._merge_linked(l, r)
def _merge_linked(
self,
l: ListNode | None,
r: ListNode | None,
) -> ListNode | None:
# The dummy node removes special handling for the result's head.
dummy = ListNode()
tail = dummy
while l and r:
# Take from the left on equality to preserve stability.
if l.val <= r.val:
tail.next = l
l = l.next
else:
tail.next = r
r = r.next
tail = tail.next
# The remaining list is already sorted, so attach it directly.
tail.next = l if l else r
return dummy.next