Sort List [Linked List MergeSort]
148.Sort List
Linked List
Sorting
Divide and Conquer
Two Pointers
Problem Statement:
Given the head of a linked list, return the list after sorting it in ascending order. Must use O(n log n) time complexity and O(1) extra space.
Example:
Input:
head = [4,2,1,3]→
Output:
[1,2,3,4]Algorithm:
- Use merge sort approach with linked list
- Find middle using slow/fast pointers
- Recursively sort both halves
- Merge sorted halves
Complexity:
Time: O(n log n) | Space: O(log n) for recursion stack
Java Solution:
public ListNode sortList(ListNode head) {
// Base case: empty list or single node
if (head == null || head.next == null)
return head;
// Step 1: Find middle using slow/fast pointers
ListNode prev = null, slow = head, fast = head;
while (fast != null && fast.next != null) {
prev = slow;
slow = slow.next;
fast = fast.next.next;
}
prev.next = null; // Cut the list in half
// Step 2: Recursively sort both halves
ListNode l1 = sortList(head);
ListNode l2 = sortList(slow);
// Step 3: Merge sorted halves
return merge(l1, l2);
}
private ListNode merge(ListNode l1, ListNode l2) {
// Create dummy node for easier merging
ListNode dummy = new ListNode(0), p = dummy;
// Merge while both lists have nodes
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
p.next = l1;
l1 = l1.next;
} else {
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
// Attach remaining nodes
if (l1 != null) p.next = l1;
if (l2 != null) p.next = l2;
return dummy.next;
}
Python Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# Base case: empty list or single node
if not head or not head.next:
return head
# Step 1: Find middle using slow/fast pointers
prev = slow = fast = head
while fast and fast.next:
prev = slow
slow = slow.next
fast = fast.next.next
prev.next = None # Cut the list in half
# Step 2: Recursively sort both halves
l1 = self.sortList(head)
l2 = self.sortList(slow)
# Step 3: Merge sorted halves
return self.merge(l1, l2)
def merge(self, l1: ListNode, l2: ListNode) -> ListNode:
# Create dummy node for easier merging
dummy = p = ListNode(0)
# Merge while both lists have nodes
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
# Attach remaining nodes
p.next = l1 or l2
return dummy.next
C++ Solution:
ListNode* sortList(ListNode* head) {
// Base case: empty list or single node
if (!head || !head->next)
return head;
// Step 1: Find middle using slow/fast pointers
ListNode *prev = nullptr, *slow = head, *fast = head;
while (fast && fast->next) {
prev = slow;
slow = slow->next;
fast = fast->next->next;
}
prev->next = nullptr; // Cut the list in half
// Step 2: Recursively sort both halves
ListNode* l1 = sortList(head);
ListNode* l2 = sortList(slow);
// Step 3: Merge sorted halves
return merge(l1, l2);
}
ListNode* merge(ListNode* l1, ListNode* l2) {
// Create dummy node for easier merging
ListNode dummy(0);
ListNode* p = &dummy;
// Merge while both lists have nodes
while (l1 && l2) {
if (l1->val < l2->val) {
p->next = l1;
l1 = l1->next;
} else {
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
// Attach remaining nodes
if (l1) p->next = l1;
if (l2) p->next = l2;
return dummy.next;
}
Hello, World!