Algorithm

Move Zeroes

Two Pointer Pattern

Move Zeroes

Given an integer array nums, move all 0s to the end of it while maintaining the relative order of the non-zero elements. Note that you must do this in-place without making a copy of the array.

CONSTRAINTS
  • 1 <= nums.length <= 10^4
  • -2^3^1 <= nums[i] <= 2^3^1 - 1
  • Must be done in-place without making a copy of the array
  • Minimize the total number of operations
EXAMPLE 1
Input: nums = [0,1,0,3,12]
Output: [1,3,12,0,0]
The non-zeros 1, 3, 12 stay in that order at the front; the two zeros end up at the back.
EXAMPLE 2
Input: nums = [0]
Output: [0]
A single zero has nothing to move past, so the array is unchanged.
EXAMPLE 3
Input: nums = [1,2,3]
Output: [1,2,3]
There are no zeros, so nothing moves and the order is preserved exactly.
Is it required to maintain the relative order of the non-zero elements?
Yes, if the non-zeroes were 1, 3, 12, they must remain 1, 3, 12 at the front of the array.
Can I just copy the non-zeroes to a new array and pad with zeros?
No, the prompt strictly requires you to do this in-place without making a copy of the array.
Is there a scenario where the array contains no zeros at all?
Yes, that is possible. Your algorithm should ideally handle that with no unnecessary writes.
Does the relative order of the zeros matter at the end?
No, because all zeros are identical, their relative order is irrelevant.

Our goal is to take a list of numbers and push all the zeroes straight to the back, while keeping all the normal numbers in their original order.

The Extra Memory Trap (O(N) Space)

The naive way is to just create a brand new list. You pull out all the normal numbers, put them in the new list, and pack zeros at the end. This is extremely easy, but it requires allocating an entire second list, which ruins our goal of modifying the list natively.

python
non_zeros = [x for x in nums if x != 0]
zeros = [0] * (len(nums) - len(non_zeros))
nums[:] = non_zeros + zeros # Uses extra memory
The Two-Pointer Shortcut

Moving items to the end of a list without freezing up extra memory is a textbook scenario for the Two-Pointer Pattern. This pattern is critically important because it allows us to do "in-place" modifications without using a backup list. We can rearrange the numbers directly inside the original list using two tracking roles:
- Writer (Slow): Keeps track of where the next real number should be placed.
- Scout (Fast): Runs ahead to find real numbers.

The Swap Strategy

The Scout sweeps across the array from left to right. Every time it finds a normal number (not a zero), we swap it with the Writer's position. Then, we bump the Writer forward by one. By constantly swapping the real numbers to the front, all the zeros naturally get pushed out to the back.

python
writer = 0

for scout in range(len(nums)):
    if nums[scout] != 0:
        nums[writer], nums[scout] = nums[scout], nums[writer]
        writer += 1
Worked Example:Move Zeroes
0
0
ws
1
1
2
0
3
3
4
12
We initialize 'writer' (slow pointer) and 'scout' (fast pointer) at index 0. Scout sees a zero, so it does nothing.
0
1
1
0
ws
2
0
3
3
4
12
Scout finds 1 (not zero). We swap the elements at writer (0) and scout (1), then advance writer to index 1.
0
1
1
0
w
2
0
s
3
3
4
12
Scout advances to index 2 and sees a zero, so no swap takes place.
0
1
1
3
2
0
w
3
0
s
4
12
Scout finds 3 (not zero). We swap the elements at writer (1) and scout (3), then advance writer to index 2.
0
1
1
3
2
12
3
0
w
4
0
s
Scout finds 12 (not zero). We swap the elements at writer (2) and scout (4), pushing the remaining zero to the back.
Interactive Strategy Visualization

Two-Pointer Swap

In-Place Array Partitioning

ANCHOR
SCAN
0
0
1
1
0
2
3
3
12
4
PROCESSED IDX
0
Cur(0) is 0. Ignore. Placeholder waits.

In-Place Efficiency

We use two pointers to partition the array. The anchor pointer tracks the boundary where the next non-zero element should be placed, while the scan pointer explores new values.

Optimal Operation Count

By swapping non-zeroes with zeroes, we eliminate the need for a second pass to fill remaining slots. This achieves O(N) time with only O(1) auxiliary space.

O(N) Time · O(N) Space Copy
O(N) Time · O(1) Space Write Pointer