Problem Statement
Given a singly linked list containing 0's, 1's, and 2's, the objective is to sort the list in non-decreasing order without using extra space. The sorting should be done by changing the links
Examples
Example 1:
Input: List = {1 -> 0 -> 2 -> 1 -> 0}
Output: {0 -> 0 -> 1 -> 1 -> 2}Different Approaches
1️⃣ Counting Sort Using Three Pointers
Algorithm:
- Initialize three pointers, zeroPtr, onePtr, and twoPtr to null.
- Traverse the linked list.
- For each node:
- If the node value is 0:
- If zeroPtr is null, assign zeroPtr to the current node.
- Otherwise, append the current node to the end of the list pointed by zeroPtr and update zeroPtr to the current node.
- If the node value is 1:
- If onePtr is null, assign onePtr to the current node.
- Otherwise, append the current node to the end of the list pointed by onePtr and update onePtr to the current node.
- If the node value is 2:
- If twoPtr is null, assign twoPtr to the current node.
- Otherwise, append the current node to the end of the list pointed by twoPtr and update twoPtr to the current node.
- If the node value is 0:
- After traversal, join the three lists (if not null), linking zeroPtr to onePtr and onePtr to twoPtr.
- Return the head of the sorted list.
Code:
#include <iostream>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
ListNode* sortList(ListNode* head) {
ListNode* zeroPtr = nullptr;
ListNode* onePtr = nullptr;
ListNode* twoPtr = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
if (curr->val == 0) {
if (zeroPtr == nullptr) {
zeroPtr = curr;
} else {
zeroPtr->next = curr;
zeroPtr = curr;
}
} else if (curr->val == 1) {
if (onePtr == nullptr) {
onePtr = curr;
} else {
onePtr->next = curr;
onePtr = curr;
}
} else { // curr->val == 2
if (twoPtr == nullptr) {
twoPtr = curr;
} else {
twoPtr->next = curr;
twoPtr = curr;
}
}
curr = curr->next;
}
if (zeroPtr != nullptr) {
zeroPtr->next = (onePtr != nullptr) ? onePtr : twoPtr;
}
if (onePtr != nullptr) {
onePtr->next = twoPtr;
}
if (twoPtr != nullptr) {
twoPtr->next = nullptr;
}
return (zeroPtr != nullptr) ? head : ((onePtr != nullptr) ? zeroPtr->next : onePtr);
}
void printList(ListNode* head) {
while (head != nullptr) {
std::cout << head->val << " ";
head = head->next;
}
std::cout << std::endl;
}
int main() {
ListNode* head = new ListNode(1);
head->next = new ListNode(0);
head->next->next = new ListNode(2);
head->next->next->next = new ListNode(1);
head->next->next->next->next = new ListNode(0);
std::cout << "Original List: ";
printList(head);
head = sortList(head);
std::cout << "Sorted List: ";
printList(head);
return 0;
}OR:
class Solution {
public:
ListNode* sortList(ListNode* head) {
// Base case: If the list is empty or has only one node, it's already sorted
if (!head || !head->next) {
return head;
}
// Create dummy nodes to represent three separate linked lists:
// - `zero` for nodes with value 0
// - `one` for nodes with value 1
// - `two` for nodes with value 2
ListNode* zero = new ListNode(0);
ListNode* zeroItr = zero; // Iterator for the `zero` list
ListNode* one = new ListNode(0);
ListNode* oneItr = one; // Iterator for the `one` list
ListNode* two = new ListNode(0);
ListNode* twoItr = two; // Iterator for the `two` list
// Traverse the original linked list and distribute nodes to the respective lists
ListNode* current = head;
while (current) {
if (current->val == 0) {
// If the current node's value is 0, add it to the `zero` list
zeroItr->next = current;
zeroItr = zeroItr->next; // Move the iterator forward
} else if (current->val == 1) {
// If the current node's value is 1, add it to the `one` list
oneItr->next = current;
oneItr = oneItr->next; // Move the iterator forward
} else {
// If the current node's value is 2, add it to the `two` list
twoItr->next = current;
twoItr = twoItr->next; // Move the iterator forward
}
current = current->next; // Move to the next node in the original list
}
// Combine the three lists:
// - Link the end of the `zero` list to the beginning of the `one` list (or `two` if `one` is empty)
// - Link the end of the `one` list to the beginning of the `two` list
zeroItr->next = one->next ? one->next : two->next;
oneItr->next = two->next;
// Mark the end of the `two` list as null to terminate the combined list
twoItr->next = nullptr;
// Get the head of the final sorted list, which is the next node after the dummy `zero` node
ListNode* sortedHead = zero->next;
// Clean up the dummy nodes to free memory
delete zero;
delete one;
delete two;
// Return the head of the sorted list
return sortedHead;
}
};
Complexity Analysis:
- Time Complexity:
O(n), wherenis the number of nodes in the current linked list. - Space Complexity:
O(1)- As we are using constant extra space regardless of input size.

Join the discussion
Sign in with your account to post comments, reply to others, and participate in the conversation.
Login to Comment