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.
- 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).
head = [1,4,3,2,5,2], x = 3[1,2,2,4,3,5]head = [2,1], x = 2[1,2]head = [1,2,3], x = 4[1,2,3]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 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.
small = []
large = []
for val in list:
if val < x: small.append(val)
else: large.append(val)
return small + largeThis 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).
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.
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.
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!
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.nextStep 2: Process Node 1 (1 < 3)
Step 3: Process Node 4 (4 >= 3)
Step 4: Process Node 3 (3 >= 3)
Step 5: Process Node 2 (2 < 3)
Step 6: Process Node 5 (5 >= 3)
Step 7: Process Node 2 (2 < 3)
Step 8: Stitch and Return
Structural Reorganization Simulation
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.
By creating two separate chains, we preserve the relative order of elements within each group—a key requirement of this problem.
Time Complexity: O(N) | Space Complexity: O(1). This technique avoid complex head-update logic by using sentinel nodes.