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).

We must split the list into two groups — values below x, then values x-and-above — while keeping the original order inside each group (that is what stable means). It's the braid from Odd Even Linked List again, with one thing changed: instead of routing nodes by their position (odd vs even), we route them by a value test (val < x vs not). Everything else — grow two chains in place, then join them — carries over.

The honest first idea, and why we can do better

The direct approach: two buffers. Walk the list, push each node into a "less" list or a "greater-or-equal" list, then concatenate. Correct, and stable because we append in traversal order — but it spends O(N) extra space on the buffers. As in Odd Even, the buffers only exist to hold nodes aside; since the nodes never actually need to move in memory, we can build both groups in place and skip the buffers entirely.

The reframe: two streams, routed by the predicate

Keep two growing chains — a less chain and a more chain — each with its own tail pointer so appending is O(1). Walk the original list once; for each node, test val < x and append it to the matching chain's tail. Because we visit nodes in their original order and only ever append, order inside each chain is automatically preserved — stability comes for free from append-in-order. When the walk ends, join the less-tail to the more-head, and we're done. Each chain gets a dummy head so "append to an empty chain" is the same code as any other append — no first-node special case, the same trick used to build the result in Add Two Numbers.

python
less = Node(0)             # dummy head of the "< x" chain
more = Node(0)             # dummy head of the ">= x" chain
less_tail, more_tail = less, more

curr = head
while curr:
    if curr.val < x:
        less_tail.next = curr
        less_tail = curr
    else:
        more_tail.next = curr
        more_tail = curr
    curr = curr.next

more_tail.next = None       # terminate the "more" chain
less_tail.next = more.next  # join: less chain -> first real "more" node
return less.next
Crucial Notemore_tail.next = None is not optional — it is the bug everyone hits. As we route nodes, we overwrite each chain's tail link but never clear the tail node's old forward pointer. The last node we place in the "more" chain still carries whatever next it had in the original list, which may point at a node we moved into the "less" chain. Leave it and you get a cycle: traversal falls off the more chain, lands back in the less chain, and loops forever. Cutting more_tail.next to null seals the end. (The less chain doesn't need an explicit cut because we overwrite its tail with more.next in the very next line.)
Worked Example:[1, 4, 3, 2, 5, 2], x = 3
- 1 < 3 → less. less: 1.
- 4 ≥ 3 → more. more: 4.
- 3 ≥ 3 → more. more: 4 → 3.
- 2 < 3 → less. less: 1 → 2.
- 5 ≥ 3 → more. more: 4 → 3 → 5.
- 2 < 3 → less. less: 1 → 2 → 2.
- Terminate: more tail 5's next → null (it had pointed at the second 2, which now lives in the less chain — the cycle we just avoided).
- Join: less tail (second 2)'s next → first real more node, 4.
- Result: 1 → 2 → 2 → 4 → 3 → 5. Each group is in original order; the groups are separated but not sorted.
The technique, and the trap to keep

One pass, fixed pointers: O(N) time, O(1) space. This is the twin of Odd Even Linked List — split one list into two by walking once and routing each node, then join — with the routing rule swapped from parity to a value predicate. The transferable reflex is that pairing: dummy-headed chains + tail pointers + null-terminate the trailing chain before joining. Whenever a problem says "group these into two (or more) categories, in place, keeping order," reach for exactly this braid and remember to sever the old tail link, or a silent cycle will bite you.

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