08. Merge Sort for Linked List
β GFG solution to the Merge Sort for Linked List problem: efficiently sort a linked list using divide and conquer approach with merge sort algorithm. π
The problem can be found at the following link: π Question Link
π§© Problem Description
You are given the head of a linked list. Your task is to sort the given linked list using Merge Sort algorithm.
Merge Sort is a divide-and-conquer algorithm that works by recursively dividing the list into smaller sublists, sorting them, and then merging them back together in sorted order.
π Examples
Example 1
Input:
Linked List: 40 -> 20 -> 60 -> 10 -> 50 -> 30
Output: 10 -> 20 -> 30 -> 40 -> 50 -> 60
Explanation: After sorting the given linked list, the resultant list will be in ascending order.Example 2
Input:
Linked List: 9 -> 5 -> 2 -> 8
Output: 2 -> 5 -> 8 -> 9
Explanation: After sorting the given linked list, the resultant list will be in ascending order.π Constraints
$1 \le \text{number of nodes} \le 10^5$
$0 \le \text{node->data} \le 10^6$
β
My Approach
The optimal approach uses the Divide and Conquer strategy with Merge Sort algorithm specifically adapted for linked lists:
Recursive Divide and Conquer
Base Case:
If the list is empty or has only one node, it's already sorted - return it.
Divide Phase:
Find the middle of the linked list using the slow-fast pointer technique.
Split the list into two halves at the middle point.
Break the connection between the two halves.
Conquer Phase:
Recursively sort the left half.
Recursively sort the right half.
Merge Phase:
Merge the two sorted halves into a single sorted list.
Compare elements from both lists and link them in ascending order.
Return Result:
Return the head of the merged sorted list.
Key Implementation Details:
Finding Middle: Use two pointers - slow moves one step, fast moves two steps. When fast reaches end, slow is at middle.
Merging: Compare data of nodes from both lists and link smaller ones first, ensuring sorted order.
Memory Efficient: No extra space needed for arrays - works directly with list nodes.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(n log n), where n is the number of nodes in the linked list. We divide the list into halves (log n levels) and at each level we traverse all n nodes for merging.
Expected Auxiliary Space Complexity: O(log n), due to the recursion stack depth. In the worst case, we have log n recursive calls on the call stack simultaneously.
π§βπ» Code (C++)
class Solution {
public:
Node *mergeSort(Node *h) {
if (!h || !h->next) return h;
Node *s = h, *f = h->next;
while (f && f->next) s = s->next, f = f->next->next;
Node *r = s->next;
s->next = nullptr;
return merge(mergeSort(h), mergeSort(r));
}
Node *merge(Node *a, Node *b) {
if (!a) return b;
if (!b) return a;
if (a->data <= b->data) {
a->next = merge(a->next, b);
return a;
}
b->next = merge(a, b->next);
return b;
}
};β Code (Java)
class Solution {
public Node mergeSort(Node h) {
if (h == null || h.next == null) return h;
Node s = h, f = h.next;
while (f != null && f.next != null) {
s = s.next;
f = f.next.next;
}
Node r = s.next;
s.next = null;
return merge(mergeSort(h), mergeSort(r));
}
Node merge(Node a, Node b) {
if (a == null) return b;
if (b == null) return a;
if (a.data <= b.data) {
a.next = merge(a.next, b);
return a;
}
b.next = merge(a, b.next);
return b;
}
}π Code (Python)
class Solution:
def mergeSort(self, h):
if not h or not h.next: return h
s, f = h, h.next
while f and f.next:
s, f = s.next, f.next.next
r = s.next
s.next = None
return self.merge(self.mergeSort(h), self.mergeSort(r))
def merge(self, a, b):
if not a: return b
if not b: return a
if a.data <= b.data:
a.next = self.merge(a.next, b)
return a
b.next = self.merge(a, b.next)
return bπ§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
π§βπ» Code (C++)
class Solution {
public:
Node *mergeSort(Node *h) {
if (!h || !h->next) return h;
Node *s = h, *f = h->next;
while (f && f->next) s = s->next, f = f->next->next;
Node *r = s->next;
s->next = nullptr;
return merge(mergeSort(h), mergeSort(r));
}
Node *merge(Node *a, Node *b) {
if (!a) return b;
if (!b) return a;
if (a->data <= b->data) {
a->next = merge(a->next, b);
return a;
}
b->next = merge(a, b->next);
return b;
}
};β Code (Java)
class Solution {
public Node mergeSort(Node h) {
if (h == null || h.next == null) return h;
Node s = h, f = h.next;
while (f != null && f.next != null) {
s = s.next;
f = f.next.next;
}
Node r = s.next;
s.next = null;
return merge(mergeSort(h), mergeSort(r));
}
Node merge(Node a, Node b) {
if (a == null) return b;
if (b == null) return a;
if (a.data <= b.data) {
a.next = merge(a.next, b);
return a;
}
b.next = merge(a, b.next);
return b;
}
}π Code (Python)
class Solution:
def mergeSort(self, h):
if not h or not h.next: return h
s, f = h, h.next
while f and f.next:
s, f = s.next, f.next.next
r = s.next
s.next = None
return self.merge(self.mergeSort(h), self.mergeSort(r))
def merge(self, a, b):
if not a: return b
if not b: return a
if a.data <= b.data:
a.next = self.merge(a.next, b)
return a
b.next = self.merge(a, b.next)
return bLast updated