← All questions

Move Zeroes

Easy Two Pointers

Given an integer array nums, move all 0s to the end while keeping the relative order of the non-zero elements. You must do this in place without making a copy of the array; the function returns nothing and mutates nums directly.

Examples

Input:  nums = [0,1,0,3,12]   -> [1,3,12,0,0]
Input:  nums = [0]            -> [0]
Input:  nums = [1,2,3]        -> [1,2,3]

Constraints

  • 1 <= len(nums) <= 10^4
  • -2^31 <= nums[i] <= 2^31 - 1

Solution

Approach — slow/fast pointers with a swap

The requirement to keep the non-zero elements in their original relative order (stability) rules out sorting or two-ends swapping. The clean stable technique is a slow/fast pointer pair.

fast scans the array. slow marks the next slot where a non-zero value belongs. Every time fast finds a non-zero, we swap it into nums[slow] and advance slow. Non-zeros get packed toward the front in order, and the zeros they displace bubble toward the back automatically.

Solution

def move_zeroes(nums: list[int]) -> None:
    slow = 0                             # next slot for a non-zero value
    for fast in range(len(nums)):
        if nums[fast] != 0:
            nums[slow], nums[fast] = nums[fast], nums[slow]
            slow += 1

Explanation

  • Why order is preserved: fast visits elements left to right, and each non-zero is placed at the next available slow slot in that same order — so their relative sequence never changes. The swap sends whatever was at slow (always a 0 once we've fallen behind) out to fast's position, pushing zeros rightward.
  • Why the swap is harmless when there are no leading zeros: while slow == fast (no zeros seen yet), the swap exchanges an element with itself — a no-op — so the algorithm costs nothing extra on already-packed prefixes.
  • The invariant: at every step, nums[0..slow) holds all non-zeros seen so far in order, and nums[slow..fast) holds only zeros. When the scan ends, all non-zeros are packed at the front and all zeros trail behind.

Complexity

  • Time: O(n) — one pass, each swap is O(1).
  • Space: O(1) — fully in place, just two index variables.

Interview tips

If you don't need to minimize writes, an alternative is: copy all non-zeros forward with slow, then fill the remainder with zeros — same complexity, marginally more writes but sometimes clearer. The swap version minimizes writes (it only touches elements that actually move). Interviewers may ask you to prove stability; point to the left-to-right scan placing each non-zero at the next slot as the argument.

Related problems