Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
A stable partition: keep an `insert` index, copy each non-zero element to `nums[insert++]`, then zero-fill from `insert` to the end. O(n) time, O(1) space.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you can do a stable in-place partition with a write pointer.
Where candidates slip
Reordering non-zeros, or leaving stale values in the tail.
How to stand out
Mention the single-pass swap variant and the shared pattern with remove-element.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 1 · Optimal
Write-pointer partition
1Hint 1Explore hintHide hint
Keep a write index for where the next non-zero should land.
2Hint 2Explore hintHide hint
Copy non-zeros forward in order; what's left over must be zeros.
3Hint 3Explore hintHide hint
Fill from the write index to the end with 0.
A · Core idea
Compact the non-zeros to the front with a write pointer, then fill the rest with zeros. This is a stable in-place partition: O(n) time, O(1) space, and the non-zeros keep their original order.
How the write pointer works. insert marks where the next kept element goes. Scanning left to right, every time you see a non-zero you copy it to nums[insert] and advance insert. Because you read and write left to right and the write index never outpaces the read index, you never clobber an unread value — and the relative order of non-zeros is preserved.
Why the second loop. After compaction, indices insert..n−1 hold stale values; overwrite them with 0. The count of zeros equals n − insert, automatically.
The swap variant. You can also swap a non-zero at the read pointer with the slot at the write pointer, avoiding the second pass — but the copy-then-fill version is the clearest to reason about. This compaction pattern reappears in 'remove element' and 'remove duplicates from sorted array'.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
nums = [0, 1, 0, 3, 12]0
skip
insert=0[1, 3, 12, 0, 0]C · Code with teaching comments
D · Why it works and complexityO(n) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
This stable-partition pattern (compact, then fill) reappears in 'remove element' and 'remove duplicates from sorted array'.
ComplexityO(n) time, O(1) space — two linear passes (compact, then fill) with only an index variable — O(n) time, O(1) space.
E · Edge cases and pitfalls5nums = [0, 0, 1] — One non-zero compacts → [1, 0, 0].Explore edge casesHide edge cases
Edge cases handled
nums = [0, 0, 1]One non-zero compacts → [1, 0, 0].nums = [1, 2, 3]No zeros → unchanged.nums = [0, 0, 0]All zeros → unchanged after fill.
Pitfalls
- Swapping in a way that reorders the non-zeros.
- Forgetting to zero-fill the remaining slots.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic void moveZeros(int[] nums) { int insert = 0; for (int x : nums) { if (x != 0) nums[insert++] = x; }Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
- Swapping in a way that reorders the non-zeros.
- Forgetting to zero-fill the remaining slots.
Revise
Carry the pattern into the interview
Pattern to remember
Stable write-pointer partition
Code pattern to memorize
insert=0; for x: if x!=0: a[insert++]=x; fill a[insert..] = 0Rules to remember
- 1Compact keepers to the front.
- 2Fill the rest with the removed value.
- 3Order preserved.
Use this pattern when
- In-place remove/move with order preserved
Interview takeaway
A write index turns 'remove/move X' into one in-place pass.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternA core fresher pattern: Stable write-pointer partition. Master it on small inputs and it transfers to harder problems.
Practice queueDirect variations and pattern siblings
Direct follow-ups
- Remove ElementComing soonSame write-pointer compaction for a target value.
- Remove Duplicates from Sorted ArrayComing soonWrite-pointer keeps the first of each run.