Rearrange Linked List
Rearrange Linked List
Category
Linked Lists
Difficulty
Hard
Problem Statement
Given a singly linked list and an integer pivot value k, rearrange the linked list so that all nodes with values less than k come first, followed by all nodes with values equal to k, followed by all nodes with values greater than k. The relative order of nodes within each partition should be preserved (stable partition). The rearrangement should be done in place.
Intuition
This is a three-way partition of a linked list, similar to the Dutch National Flag problem on arrays. We can create three separate lists (less than, equal to, greater than) by traversing the original list once, then concatenate them. Since we are rearranging existing nodes (not creating new ones), this uses O(1) extra space beyond a few pointers.
Approach
- Initialize three pairs of pointers: (lessHead, lessTail), (equalHead, equalTail), and (greaterHead, greaterTail), all set to null.
- Traverse the original linked list node by node.
- For each node, compare its value to k and append it to the appropriate partition list.
- After traversal, concatenate the three lists: less -> equal -> greater.
- Handle cases where one or more partitions are empty.
- Set the
nextpointer of the last node in the combined list to null. - Return the head of the combined list.
Pseudocode
function rearrangeLinkedList(head, k):
lessHead = lessTail = null
equalHead = equalTail = null
greaterHead = greaterTail = null
current = head
while current is not null:
nextNode = current.next
current.next = null
if current.value < k:
if lessHead is null:
lessHead = lessTail = current
else:
lessTail.next = current
lessTail = current
else if current.value == k:
if equalHead is null:
equalHead = equalTail = current
else:
equalTail.next = current
equalTail = current
else:
if greaterHead is null:
greaterHead = greaterTail = current
else:
greaterTail.next = current
greaterTail = current
current = nextNode
// Connect partitions
head = connectPartitions(lessHead, lessTail, equalHead, equalTail, greaterHead, greaterTail)
return head
function connectPartitions(lH, lT, eH, eT, gH, gT):
// Connect less -> equal -> greater, skipping empty partitions
if lT is not null:
lT.next = eH if eH is not null else gH
if eT is not null:
eT.next = gH
firstHead = lH if lH is not null else (eH if eH is not null else gH)
return firstHead
Time & Space Complexity
- Time: O(n) where n is the number of nodes. Single pass through the list plus constant-time concatenation.
- Space: O(1) extra space. Only a fixed number of pointers are used; no new nodes are created.
Key Insights
- Maintaining both head and tail pointers for each partition enables O(1) appending and O(1) concatenation.
- Detaching each node (
current.next = null) before appending prevents cycles in the rearranged list. - The algorithm is stable — nodes within each partition maintain their original relative order.
- This is analogous to the partition step of quicksort but on a linked list with three-way partitioning.
- The pivot value k does not need to be present in the list.
Edge Cases
- The list is empty — return null.
- All nodes have the same value — the list is unchanged.
- No nodes equal to k — the equal partition is empty and is skipped during concatenation.
- Only one partition is non-empty — the list is already correctly arranged.
- k is smaller than all values or larger than all values — one of the extreme partitions gets all nodes.
- The list has only one node — return it unchanged.