Community Problem
Move Zeroes
Difficulty: Easy
Move every zero to the end of the array in place while keeping the relative order of the non-zero elements.
Move Zeroes
Move every zero to the end of the array in place while keeping the relative order of the non-zero elements.
By @rajtanaka
February 7, 2026
·
Updated May 18, 2026
505 views
7
4.2 (10)
I see this one in the first 15 minutes of a screen more than almost any other Easy, usually right after a candidate gets through Two Sum. The reason is the relative-order constraint: it rules out the swap-from-the-ends shortcut and forces the cleaner write-pointer pattern that scales to the harder "compact in place" family (Remove Element, Remove Duplicates from Sorted Array, etc.).
Move Zeroes
Given an integer array nums, move all 0s to the end of the array while keeping the relative order of the non-zero elements unchanged. You must do this in place without allocating a new array. The function does not need to return anything; modify nums directly.
Examples
Example 1:
- Input:
nums = [0, 1, 0, 3, 12] - Output:
numsbecomes[1, 3, 12, 0, 0] - Explanation: Non-zero values
1, 3, 12keep their original relative order; the two zeros land at the end.
Example 2:
- Input:
nums = [0] - Output:
numsbecomes[0] - Explanation: Single-element zero array is unchanged.
Example 3:
- Input:
nums = [1, 2, 3] - Output:
numsbecomes[1, 2, 3] - Explanation: No zeros, no rearrangement.
Example 4:
- Input:
nums = [0, 0, 1] - Output:
numsbecomes[1, 0, 0] - Explanation: Two leading zeros migrate to the back; the lone non-zero shifts forward.
Constraints
1 <= nums.length <= 10^4-2^31 <= nums[i] <= 2^31 - 1
Follow-up
Can you minimize the number of writes? The two-pointer scan with swaps does O(n) writes; the simpler "compact then pad" version does up to 2 * (count of non-zeros) writes, which is fewer when the array is mostly zeros.
Solution
Hints
Solution Walkthrough
Approach: Compact-Then-Pad with a Write Pointer (O(n) time, O(1) extra space)
The relative-order requirement is what makes this problem nontrivial. The clean answer is a write-pointer scan: a single pointer write tracks where the next non-zero value should land, while a separate read index walks the full array. Whenever read lands on a non-zero, copy it to nums[write] and advance write. After the scan, every index from write to the end gets overwritten with 0. The relative order of non-zeros is preserved because the read order is preserved.
Algorithm
- Initialize
write = 0. - For each
readfrom0ton - 1:- If
nums[read] != 0, setnums[write] = nums[read]and advancewrite.
- For each
ifromwriteton - 1, setnums[i] = 0.
Why It Works
Loop invariant after iteration read: indices 0..write - 1 contain the non-zero values from nums[0..read] in their original relative order, and the suffix nums[write..read] may contain stale data that will be overwritten. After the first loop, write equals the count of non-zeros and the suffix is the count of zeros, which the second loop fills in.
Single-Pass Swap Variant
There is also a single-pass version using two pointers and swaps:
The swap version does up to n swaps (each touching two indices), so up to 2n writes; the compact-then-pad version writes at most 2 * (count of non-zeros) slots, which is strictly fewer when zeros dominate the input.
Complexity
Metric Value
Time O(n), one or two linear passes
Space O(1) extra, all work happens in placePitfalls
- Sort or filter, then assign back. Calling
nums = nums.filter(x => x !== 0).concat(zeros)does the right thing but reassigns the local reference, which the caller never sees. Mutate in place. - Forgetting to advance
write. If you copynums[read]tonums[write]but forget thewrite++, every subsequent non-zero overwrites the same index and only the last non-zero survives. - Padding with the wrong value. The padding loop must write
0, notnullorundefined. - Two-pointer swap with read = write. When
read === write, the swap is a no-op but still costs two writes. The compact-then-pad version skips that branch entirely.
Solution Code
