Sort a Linked List Using Merge Sort in DSA Rust - Time & Space Complexity
We want to understand how the time needed to sort a linked list grows as the list gets bigger.
Specifically, how does merge sort handle this task efficiently?
Analyze the time complexity of the following code snippet.
fn merge_sort(head: Option>) -> Option> {
if head.is_none() || head.as_ref().unwrap().next.is_none() {
return head;
}
let (left, right) = split_list(head);
let sorted_left = merge_sort(left);
let sorted_right = merge_sort(right);
merge(sorted_left, sorted_right)
}
This code splits the linked list into halves, sorts each half recursively, and then merges the sorted halves.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursively splitting the list and merging sorted halves.
- How many times: The list is split about log n times, and merging touches all nodes each time.
Each split divides the list in half, and merging combines all nodes back.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * 3.3 = 33 |
| 100 | About 100 * 6.6 = 660 |
| 1000 | About 1000 * 10 = 10,000 |
Pattern observation: Operations grow roughly as n times log n, meaning doubling the list size adds a bit more than double the work.
Time Complexity: O(n log n)
This means the time to sort grows a little faster than the size of the list, but much better than checking every pair.
[X] Wrong: "Sorting a linked list with merge sort is O(n²) because of all the splitting and merging."
[OK] Correct: The splitting happens in log n steps, and merging touches all nodes each step, so total work is n times log n, not n squared.
Understanding merge sort on linked lists shows you can handle recursion and pointers well, a skill many interviews look for.
"What if we used quicksort instead of merge sort on the linked list? How would the time complexity change?"
Practice
Solution
Step 1: Understand linked list access
Linked lists do not support fast random access, unlike arrays.Step 2: Compare sorting algorithms
Merge sort works well with sequential access by splitting and merging, while quicksort relies on random access for partitioning.Final Answer:
Merge sort does not require random access, which suits linked lists well. -> Option CQuick Check:
Linked list + merge sort = no random access needed [OK]
- Thinking quicksort is always faster
- Assuming merge sort sorts in place without extra space
- Confusing memory usage between merge sort and quicksort
Solution
Step 1: Understand ownership in Rust linked lists
Rust requires ownership for heap data; Box<T> owns heap data, Option allows None or a node.Step 2: Analyze options
struct ListNode { val: i32, next: Option } uses Option which is correct for nullable next pointer. Others use references without ownership or missing Option.Final Answer:
struct ListNode { val: i32, next: Option } -> Option BQuick Check:
Rust linked list node uses Option [OK]
- Using references (&) without lifetime management
- Omitting Option for nullable next pointer
- Using Box<T> without Option causing no null
Solution
Step 1: Split the list into halves
Split 4->2->1->3 into 4->2 and 1->3.Step 2: Recursively sort and merge
Sort halves: 4->2 becomes 2->4, 1->3 becomes 1->3. Merge sorted halves: 1->2->3->4.Final Answer:
1 -> 2 -> 3 -> 4 -> null -> Option AQuick Check:
Sorted ascending linked list = 1->2->3->4 [OK]
- Not splitting list correctly
- Merging without sorting halves
- Confusing order of merged nodes
Solution
Step 1: Understand splitting in merge sort
Splitting requires breaking the list into two halves by setting the middle node's next pointer to None.Step 2: Identify infinite recursion cause
If next pointer is not set to None, recursive calls never reach base case, causing infinite recursion.Final Answer:
Not updating the next pointer to None when splitting the list -> Option DQuick Check:
Broken split causes infinite recursion [OK]
- Forgetting to break the list at midpoint
- Confusing Box and Rc usage
- Misusing references causing borrow errors
Solution
Step 1: Recognize duplicates in the list
The list contains duplicates: two 5s and two 3s.Step 2: Apply merge sort preserving duplicates
Merge sort sorts all nodes including duplicates, resulting in ascending order with duplicates preserved: 2->3->3->5->5.Final Answer:
2 -> 3 -> 3 -> 5 -> 5 -> null -> Option AQuick Check:
Sorted list keeps duplicates in order [OK]
- Removing duplicates by mistake
- Sorting incorrectly ignoring duplicates
- Confusing output order with duplicates
Ready to prove it?
Pass the test and this pattern moves unknown
