Algorithm

Partition List

Linked List Pattern

Partition List

Given the head of a linked list and a value x, rearrange the nodes so that every node with value less than x appears before every node with value greater than or equal to x. Within each of the two groups, the original relative order must be preserved (a stable partition). Rewire nodes in place and return the new head. Note this is only a partition, not a sort — the two groups are not internally sorted.

CONSTRAINTS
  • The number of nodes in the list is in the range [0, 200]
  • -100 <= Node.val <= 100
  • -200 <= x <= 200
  • Relative order within each partition must be preserved (stable).
EXAMPLE 1
Input: head = [1,4,3,2,5,2], x = 3
Output: [1,2,2,4,3,5]
The values below 3 are 1, 2, 2 and they lead; the values 3 or above are 4, 3, 5 and they follow. Inside each group the nodes keep the order they appeared in the original list.
EXAMPLE 2
Input: head = [2,1], x = 2
Output: [1,2]
1 is below 2 so it comes first; 2 is not below 2 (equal counts as the second group) so it follows. Note the groups are not sorted — only separated.
EXAMPLE 3
Input: head = [1,2,3], x = 4
Output: [1,2,3]
Every value is below 4, so all nodes fall in the first group and the order is unchanged.
Does a node equal to x go before or after?
After — the split is 'less than x' versus 'greater than or equal to x', so a value exactly equal to x belongs to the second group.
Do the two partitions need to be sorted internally?
No. This is a partition, not a sort: within each group nodes keep their original relative order, but the group itself is not ordered by value.
Can I swap node values instead of relinking?
You could, but the clean and intended approach relinks nodes by rewiring pointers, which is stable and O(1) space. Value swaps make stability awkward to preserve.
What if every node lands in the same group?
That's fine — one group is simply empty and the result equals the original order. The joining logic must still handle an empty group without breaking (the dummy heads make this automatic).
The Goal: Sorting Without Losing Order

Imagine you have a list of numbers, and you want to group all the "small" ones together at the front and the "large" ones at the back. The catch is that if two small numbers were in a certain order originally, they must stay in that same order in the final result.

The Brute Force: Extra Storage

The easiest way is to create two completely new lists (or arrays). We walk through the original list, throw small numbers into the first array and large ones into the second, then join them.

python
small = []
large = []
for val in list:
    if val < x: small.append(val)
    else: large.append(val)
return small + large

This works, but it uses O(N) extra space. In linked list problems, we usually want to do this in-place by just moving the arrows (pointers).

The "Two Streams" Idea

Instead of creating new arrays, we create two "dummy" starting points: one for the Small Stream and one for the Large Stream.
- As we walk through the list, we "route" each node to one of these two streams.
- We use two moving pointers (small_tail and large_tail) to keep track of where the next node should go.

The Safety Net: Dummy Heads

We use "dummy" nodes at the start of both streams so we don't have to check if the stream is empty every time we add a node. It's like having a permanent "first brick" in place so you can always add the next one after it.

Cleaning Up the Last Link

The most important step happens at the very end. The last node in our Large Stream might still be pointing to a node that we moved to the Small Stream. If we don't manually set its next to null, we could accidentally create a loop in our list!

python
less = Node(0) # Dummy head
more = Node(0) # Dummy head
l_tail, m_tail = less, more

while head:
    if head.val < x:
        l_tail.next = head
        l_tail = l_tail.next
    else:
        m_tail.next = head
        m_tail = m_tail.next
    head = head.next

m_tail.next = None       # CRITICAL: Cut off any old links
l_tail.next = more.next  # Join the two streams
return less.next
Worked Example:[1, 4, 3, 2, 5, 2], x=3
1
head
4
3
2
5
2
NULL
We start with head pointing to node 1. We initialize dummy nodes [0] for the 'less' and 'more' streams.

Step 2: Process Node 1 (1 < 3)

0
1
less_tail
NULL
Less Stream: We append 1 to the 'less' stream and advance less_tail to node 1.
0
more_tail
NULL
More Stream: Left empty with only the dummy node.

Step 3: Process Node 4 (4 >= 3)

0
1
less_tail
NULL
Less Stream: Unchanged.
0
4
more_tail
NULL
More Stream: We append 4 to the 'more' stream and advance more_tail to node 4.

Step 4: Process Node 3 (3 >= 3)

0
1
less_tail
NULL
Less Stream: Unchanged.
0
4
3
more_tail
NULL
More Stream: We append 3 to the 'more' stream and advance more_tail to node 3.

Step 5: Process Node 2 (2 < 3)

0
1
2
less_tail
NULL
Less Stream: We append 2 to the 'less' stream and advance less_tail to node 2.
0
4
3
more_tail
NULL
More Stream: Unchanged.

Step 6: Process Node 5 (5 >= 3)

0
1
2
less_tail
NULL
Less Stream: Unchanged.
0
4
3
5
more_tail
NULL
More Stream: We append 5 to the 'more' stream and advance more_tail to node 5.

Step 7: Process Node 2 (2 < 3)

0
1
2
2
less_tail
NULL
Less Stream: We append the final node 2 to the 'less' stream and advance less_tail to index 3.
0
4
3
5
more_tail
NULL
More Stream: Unchanged.

Step 8: Stitch and Return

1
2
2
4
3
5
NULL
We cut any old outgoing link from 5 by setting more_tail.next to null. Then, we stitch less_tail (2) to more.next (4) and return less.next, producing [1, 2, 2, 4, 3, 5].
Interactive Strategy Visualization
LIST PARTITION ENGINE

Structural Reorganization Simulation

1
4
3
2
5
2
READY TO START

Phase Details

1. Start Two New Lists

We create two 'placeholder' nodes: one for Small numbers and one for Large ones. This makes it easy to add nodes without checking if the list is empty.

Engineering Note

By creating two separate chains, we preserve the relative order of elements within each group—a key requirement of this problem.

Strategy: Dual-Dummy Partition

Time Complexity: O(N) | Space Complexity: O(1). This technique avoid complex head-update logic by using sentinel nodes.

O(N) Time · O(N) Space Two Buffers
O(N) Time · O(1) Space Stable In-Place Routing