Last Updated: March 29, 2026
This problem is essentially asking us to do a stable partition on a linked list. We need to split the nodes into two groups based on a threshold value x: nodes with values less than x, and nodes with values greater than or equal to x. Within each group, the original order must be preserved.
The word "preserve" is critical here. If we just moved nodes around carelessly, we might get all the right values in the right half, but in the wrong order. For example, with [1, 4, 3, 2, 5, 2] and x = 3, we can't output [2, 2, 1, 3, 5, 4] even though that also has all the "less than 3" values first. The relative order within each group has to match the original list.
The key observation is that we're not sorting. We're partitioning. Two nodes that are both less than x should appear in the same relative order as they did in the original list. This means we need a stable approach, not just any rearrangement.
0 <= n <= 200 -> With at most 200 nodes, even an O(n^2) solution would be nearly instant. But there's no reason to go beyond O(n) for a linked list partition.-100 <= Node.val <= 100 -> Small value range. Values can be negative, and they can equal x. The condition is strictly "less than," so nodes equal to x go into the "greater than or equal to" group.-200 <= x <= 200 -> The partition value x might not even appear in the list. It could also be smaller than all values or larger than all values.The most straightforward way to think about this: traverse the linked list, collect all node values into an array, partition the array (preserving order), and then build a new linked list from the partitioned values.
This sidesteps all the tricky pointer manipulation. We just work with arrays, which are easier to reason about, and then convert back.
x, one for values greater than or equal to x.Input:
After partitioning into two groups:
Concatenate and rebuild:
This approach works correctly but uses extra memory by creating new nodes. What if we rearranged the existing nodes by manipulating their next pointers instead?
Instead of copying values, we can rewire the existing nodes into two separate chains. One chain collects all nodes with values less than x, and the other collects all nodes with values greater than or equal to x. Then we just connect the tail of the first chain to the head of the second chain.
The trick that makes this clean is using dummy head nodes. Without dummy nodes, we'd need special-case logic for the first node added to each chain. A dummy node acts as a placeholder so we can always append to tail.next without checking if the chain is empty.
We're essentially unzipping the original list into two independent chains and then zipping them back in the right order. Because we process nodes from left to right and always append to the tail, the relative order within each chain matches the original list. That's what makes this a stable partition.
The dummy nodes eliminate all the edge cases. Without them, we'd need to check "is this the first node in the chain?" every time we append. The dummy gives us a guaranteed non-null tail to append to from the very start.
lessHead and greaterHead. These will serve as the anchors for our two chains.lessTail and greaterTail, both pointing to their respective dummy nodes.node.val < x, append it to the "less" chain.lessTail.next = greaterHead.next (skip the dummy).greaterTail.next = null to avoid cycles.lessHead.next (skip the dummy).