You're handed an integer array nums. Slide every 0 to the end of the array while keeping the relative order of the non-zero numbers exactly as it was.
The catch: you must do this in-place — no copying the answer into a brand-new array. Only the values inside nums may move.
For example, [0,1,0,3,12] becomes [1,3,12,0,0]: the non-zeros 1, 3, 12 stay in their original order, and both zeros collect at the back.
nums directly. Our judge reads the final state of nums (returned here for convenience), so both the mutation and the returned reference describe the same array.i == insert — the element is already in place, so a self-swap is wasted work.Input: nums = [0,1,0,3,12] Output: [1,3,12,0,0] The non-zeros 1, 3, 12 keep their order; the two 0's move to the end.
Input: nums = [0] Output: [0] A single zero is already at the end.
- 1 <= nums.length <= 10^4 - -2^31 <= nums[i] <= 2^31 - 1
Move Zeroes is a stable in-place partition in disguise: keep the non-zeros in order up front and let the zeros fall to the back. It's the same partition engine as quicksort and the Dutch-flag problem, and it teaches the single-write-pointer trick you'll reuse constantly.
scan pointer visiting every element and an insert pointer marking where the next non-zero belongs.O(1) space.Given an array nums, move every 0 to the end in place while keeping the relative order of the non-zero values.
Worked example — nums = [0, 1, 0, 3, 12]
scan 0 → zero, skip insert=0 scan 1 → non-zero, swap into slot 0 [1,0,0,3,12] insert=1 scan 0 → zero, skip insert=1 scan 3 → non-zero, swap into slot 1 [1,3,0,0,12] insert=2 scan 12 → non-zero, swap into slot 2 [1,3,12,0,0] insert=3 ✓
“Does the relative order of the non-zeros have to be preserved?”
Yes — that's what makes it a stable partition and rules out simply swapping zeros to the end from both directions.
“Do I mutate in place or return a new array?”
In place — no second array whose size grows with the input.
“What if there are no zeros?”
The array is already correct; the swap should be a no-op (ideally skipped entirely).
“What if every element is zero, or the array has one element?”
Nothing moves — the insert pointer simply never advances.
“Should I minimise the number of writes?”
A nice follow-up: only swap on a real non-zero, and skip the self-swap when scan == insert.
“How large can the array be?”
Up to 10^4. Both approaches are O(n); the two-pointer version wins on space and does it in one pass.
Two quick questions.
Do the non-zeros need to keep their original relative order?
This is strictly in place, no extra array?
Then I'll use one pass with an insert pointer, swapping each non-zero to the front.
You're not ordering the values — you're splitting them into two groups (non-zero, then zero) while keeping the non-zeros in their original sequence. Recognising it as a stable partition tells you a single pass with one boundary pointer is enough.
Let insert be the index of the next slot reserved for a non-zero. Scan the array; every time you meet a non-zero, place it at insert and advance insert. After the scan, everything before insert is the non-zeros in order and everything after is zeros — no separate zero-filling needed if you swap.
Swapping the non-zero forward into insert (rather than shifting or filling from the end) both preserves relative order and leaves a zero behind to bubble toward the back. Skipping the swap when scan == insert avoids wasted self-swaps when the prefix is already zero-free.
| Scratch array | In-place swap | |
|---|---|---|
| Idea | Copy non-zeros out, backfill zeros | Swap non-zeros forward as you scan |
| Time | O(n) | O(n) |
| Space | O(n) | O(1) |
| Passes | 2 | 1 |
The full code for both is in the Approaches selector below.
Key takeaway
Treat Move Zeroes as a stable in-place partition: a single insert pointer marks where the next non-zero belongs, and you swap each non-zero forward as you scan. One O(n) pass, O(1) space, order preserved — the same partition step that drives quicksort.