29. Sort a Linked List of 0s, 1s, and 2s
The problem can be found at the following link: 🔗 Question Link
🧩 Problem Description
Given the head of a linked list where each node contains a value of either 0, 1, or 2, your task is to rearrange the list such that all 0s appear first, followed by all 1s, and all 2s appear at the end.
📘 Examples
Example 1:
Input:
head = 1 → 2 → 2 → 1 → 2 → 0 → 2 → 2
Output:
0 → 1 → 1 → 2 → 2 → 2 → 2 → 2
Explanation:
After sorting, all the 0s are at the beginning, followed by the 1s, and all the 2s appear at the end of the list.
Example 2:
Input:
head = 2 → 2 → 0 → 1
Output:
0 → 1 → 2 → 2
Explanation:
After sorting, the list is rearranged to have 0 at the beginning, followed by 1, and all 2s at the end.
🔒 Constraints
$( 1 \leq \text{no. of nodes} \leq 10^6 )$
$( 0 \leq node->data \leq 2 )$
✅ My Approach
Optimized Approach (Dutch National Flag Problem)
The problem can be solved using a modified version of the Dutch National Flag problem, which is known for sorting three distinct elements efficiently.
Algorithm Steps:
Three Pointers Approach:
Initialize three pointers:
low,mid, andhigh.Traverse the list and:
If the current node’s value is
0, move it to the beginning (incrementlow).If the current node’s value is
1, keep it in the middle (incrementmid).If the current node’s value is
2, move it to the end (decrementhigh).
Pointer Movement:
The
lowpointer tracks the end of the 0s section.The
midpointer tracks the current node.The
highpointer tracks the start of the 2s section.
End Condition:
The loop ends when
midcrosseshigh.
🧮 Time and Auxiliary Space Complexity
Expected Time Complexity: O(n), where
nis the number of nodes in the list. We only traverse the list once.Expected Auxiliary Space Complexity: O(1), as we use a constant amount of extra space for the pointers.
🧠 Code (C++)
⚡ Alternative Approaches
📊 2️⃣ Node Rearrangement with Dummy Nodes
Algorithm Steps:
Create three dummy nodes for sublists of 0s, 1s, and 2s.
Traverse the original list and attach nodes to respective lists.
Connect the three sublists in order and return the new head.
✅ Why This Approach?
Maintains original nodes — no value rewriting.
Good for cases where mutating node values is not allowed.
📝 Complexity Analysis:
Time Complexity: O(n), where
nis the number of nodes in the linked list. We traverse the list once.Auxiliary Space Complexity: O(1) as no extra data structures other than dummy nodes are used.
📊 3️⃣ Extract, Sort & Reassign
Algorithm Steps:
Traverse the list and collect all node values into a
std::vector<int>.Sort the vector.
Traverse the list again, overwriting each node’s
datawith the corresponding sorted value.
✅ Why This Approach?
Simple to implement, leverages built-in sorting.
Suitable for environments where the list can be temporarily transformed into an array for sorting.
📝 Complexity Analysis:
Time Complexity: O(n log n) due to the sorting step.
Auxiliary Space Complexity: O(n) for the vector to store node values.
📊 4️⃣ In‐Place Node Insertion
Algorithm Steps:
Maintain two pointers:
tail0(end of 0s sublist) andprev/curr.First pass: whenever
curr->data == 0, detachcurrand insert it aftertail0(or at head iftail0is null), advancetail0.Second pass (starting from
tail0->next): similarly extract1s and insert after the end of the 1s sublist.Remaining nodes are all 2s by default.
✅ Why This Approach?
No extra memory for node values (only pointer manipulation).
Efficient for cases where you need to segregate nodes without rewriting data.
📝 Complexity Analysis:
Time Complexity: O(n), where
nis the number of nodes in the list. We perform two passes over the list.Auxiliary Space Complexity: O(1), as the algorithm only uses a few pointer variables for manipulation.
🆚 Comparison of Approaches
Approach
⏱️ Time
🗂️ Space
✅ Pros
⚠️ Cons
Value Overwrite
🟢 O(n)
🟢 O(1)
Short, fastest, easy to code
Mutates values directly
Node Rearrangement
🟢 O(n)
🟢 O(1)
Does not change node data
Slightly longer, uses extra dummy nodes
Extract & Sort
🔸 O(n log n)
🔴 O(n)
Very simple to implement
Extra memory, slower due to sort
In‐Place Node Insertion
🟢 O(n)
🟢 O(1)
No extra allocations, preserves original nodes
Code is more intricate, careful pointer handling
✅ Best Choice?
Scenario
Recommended Approach
Minimal code and max speed
🥇 Value Overwrite
Cannot mutate node values
🥈 Node Rearrangement
Memory is abundant, simplicity preferred
🥉 Extract & Sort
Strict no-allocation and O(1) overhead
🎖️ In‐Place Node Insertion
🧑💻 Code (Java)
🐍 Code (Python)
🧠 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
Last updated