Skip to content

Sort List

Sort a linked list in O(n log n) time and O(1) or O(log n) space complexity. Use merge sort for divide and conquer.

InputOutput
4 -> 2 -> 1 -> 31 -> 2 -> 3 -> 4
-1 -> 5 -> 0-1 -> 0 -> 5
  • The number of nodes in the list is in the range [0, 5 * 10^4].
  • -10^5 <= Node.val <= 10^5
ApproachTimeSpace
RecursiveO(n log n)O(log n)
IterativeO(n log n)O(1)
  • Pick Recursive for clarity — mirrors typical divide and conquer pattern.
  • Pick Iterative for minimal space and interview confidence.
Pattern Match
Recursive
O(n log n) time · O(log n) space
Space Optimal
Iterative
O(n log n) time · O(1) space
Section titled “Approach 1: Recursive Merge Sort (Recommended)”
★ Recommended
  1. Find middle using slow/fast pointers.
  2. Split list into two halves.
  3. Recursively sort both halves.
  4. Merge sorted halves.
⏱ Time O(n log n) Divide and conquer 💾 Space O(log n) Call stack depth
sort_list_recursive.py
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def sortList(head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return head
slow, fast = head, head.next
prev = None
while fast and fast.next:
prev = slow
slow = slow.next
fast = fast.next.next
if prev:
prev.next = None
left = sortList(head)
right = sortList(slow)
return merge(left, right)
def merge(l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0)
curr = dummy
while l1 and l2:
if l1.val <= l2.val:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
curr = curr.next
curr.next = l1 if l1 else l2
return dummy.next
# Example usage
head = ListNode(4, ListNode(2, ListNode(1, ListNode(3))))
result = sortList(head)
while result:
print(result.val, end=" ")
result = result.next
print()

Approach 2: Iterative Bottom-up Merge Sort

Section titled “Approach 2: Iterative Bottom-up Merge Sort”
🎯 Interview Favourite

Use nested loops: outer loop controls merge size (1, 2, 4, 8, …), inner loop merges adjacent chunks.

⏱ Time O(n log n) Divide and conquer 💾 Space O(1) No extra space
sort_list_iterative.py
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def sortList(head: Optional[ListNode]) -> Optional[ListNode]:
if not head:
return head
length = 0
curr = head
while curr:
length += 1
curr = curr.next
dummy = ListNode(0, head)
size = 1
while size < length:
curr = dummy.next
tail = dummy
while curr:
l1 = curr
l1_end = l1
l1_len = 0
while l1_len < size and l1_end:
l1_end = l1_end.next
l1_len += 1
l2 = l1_end
l2_len = 0
while l2_len < size and l2:
l2 = l2.next
l2_len += 1
l1_end = l1
for _ in range(l1_len - 1):
if l1_end:
l1_end = l1_end.next
if l1_end:
l1_end.next = None
tail.next = merge(l1, l2)
while tail.next:
tail = tail.next
curr = l2
size *= 2
return dummy.next
def merge(l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0)
curr = dummy
while l1 and l2:
if l1.val <= l2.val:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
curr = curr.next
curr.next = l1 if l1 else l2
return dummy.next
# Example usage
head = ListNode(4, ListNode(2, ListNode(1, ListNode(3))))
result = sortList(head)
while result:
print(result.val, end=" ")
result = result.next
print()
✓ Simple

A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.

⏱ Time O(n) Optimized complexity 💾 Space O(1) Efficient space usage
function approach3():
// Implementation approach goes here
sort_list_space_optimized.py
"""
Solution for Sort List
"""
def solve():
"""Implementation for approach 3 of Sort List"""
pass
if __name__ == "__main__":
print("Solution ready")