const solve = (nums) => { let left = 0, right = nums.length - 1; while (left < right) { const sum = nums[left] + nums[right]; if (sum === target) return [left, right]; }}
Problem Walkthrough

Move Zeroes: LeetCode 283 Solution Explained

Move Zeroes (#283) teaches the same-direction two-pointer partition pattern — the simplest in-place array rearrangement problem.

6 min read|

Move Zeroes (#283): the simplest two-pointer partition

Same-direction pointers — the in-place rearrangement pattern for arrays

Move Zeroes: The Simplest Two-Pointer Partition

Move Zeroes (#283) is one of the most popular Easy problems on LeetCode, and for good reason. It distills the same-direction two-pointer partition pattern down to its purest form — move all zeros to the end of an array while keeping the relative order of non-zero elements intact.

This problem appears deceptively simple, but the technique it teaches is foundational. The same partition logic powers Remove Duplicates (#26), Sort Colors (#75), and dozens of other array manipulation problems. If you can solve Move Zeroes cleanly, you already understand the core mechanic behind in-place array rearrangement.

In this walkthrough, we will break down the move zeroes leetcode problem step by step, from understanding the constraints to implementing the optimal O(n) solution with O(1) space.

Understanding the Problem

Given an integer array nums, move all zeros to the end of the array while maintaining the relative order of the non-zero elements. You must do this in-place without making a copy of the array.

For example, given [0, 1, 0, 3, 12], the output should be [1, 3, 12, 0, 0]. The non-zero elements 1, 3, and 12 keep their original relative order, and both zeros end up at the back.

The two key constraints are what make this problem interesting. First, you must modify the array in-place — no creating a new array and copying values over. Second, you must preserve the relative order of non-zero elements, which rules out simple swap-to-end approaches that might scramble the order.

  • Input: an integer array nums containing zeros and non-zeros
  • Output: modify nums in-place so all zeros are at the end
  • Relative order of non-zero elements must be preserved
  • Must use O(1) extra space — no auxiliary arrays allowed
ℹ️

Did You Know?

Move Zeroes (#283) is one of the most solved Easy array problems — it teaches the same partition technique used in Remove Duplicates (#26) and Sort Colors (#75).

The Two-Pointer Approach for Move Zeroes

The optimal solution uses two pointers that both move left to right — a slow pointer and a fast pointer. This is the same-direction two-pointer pattern, distinct from the converging two-pointer pattern you see in problems like Two Sum II.

The slow pointer tracks where the next non-zero value should be placed. The fast pointer scans through the array looking for non-zero values. Every time the fast pointer finds a non-zero element, it swaps that element with whatever is at the slow pointer position, then both pointers advance.

Why does this work? The slow pointer always stays at or behind the fast pointer. Everything before the slow pointer is already a correctly placed non-zero value. Everything between slow and fast is zeros. The swap moves each non-zero value into its correct final position while pushing zeros toward the end.

Implementation: Move Zeroes in O(n) Time

The implementation is remarkably concise. Initialize a slow pointer at index 0. Then iterate through the array with a fast pointer. Whenever you encounter a non-zero value at the fast pointer, swap it with the value at the slow pointer and increment slow.

In Python, the solution is just a few lines: set slow = 0, loop fast from 0 to len(nums)-1, and when nums[fast] != 0, swap nums[slow] and nums[fast], then increment slow. In JavaScript or TypeScript, the same logic applies with destructuring assignment for the swap.

This gives you O(n) time complexity since each element is visited exactly once by the fast pointer. Space complexity is O(1) because you only use two integer variables regardless of input size. The same partition technique appears in Sort Colors (#75), where you partition around a pivot value instead of zero.

  • Time complexity: O(n) — single pass through the array
  • Space complexity: O(1) — only two pointer variables
  • Number of swaps: at most n (each element swapped at most once)
  • The same pattern applies to Remove Duplicates (#26) and Sort Colors (#75)
💡

Key Insight

The slow pointer always points to the position where the next non-zero should go. The fast pointer scans ahead. When fast finds a non-zero, swap it into the slow position. This maintains order.

Visual Walkthrough: [0, 1, 0, 3, 12]

Let us trace through the algorithm with the classic example [0, 1, 0, 3, 12]. Both slow and fast start at index 0.

Step 1: fast=0, nums[0]=0. Zero found — do nothing. fast moves to 1. Step 2: fast=1, nums[1]=1. Non-zero found — swap nums[0] and nums[1]. Array becomes [1, 0, 0, 3, 12]. slow moves to 1, fast moves to 2.

Step 3: fast=2, nums[2]=0. Zero found — do nothing. fast moves to 3. Step 4: fast=3, nums[3]=3. Non-zero found — swap nums[1] and nums[3]. Array becomes [1, 3, 0, 0, 12]. slow moves to 2, fast moves to 4.

Step 5: fast=4, nums[4]=12. Non-zero found — swap nums[2] and nums[4]. Array becomes [1, 3, 12, 0, 0]. slow moves to 3, fast moves to 5. Loop ends. The array is now [1, 3, 12, 0, 0] — exactly the expected output.

  1. 1fast=0: nums[0]=0, skip. Array: [0, 1, 0, 3, 12]
  2. 2fast=1: nums[1]=1, swap with slow=0. Array: [1, 0, 0, 3, 12]
  3. 3fast=2: nums[2]=0, skip. Array: [1, 0, 0, 3, 12]
  4. 4fast=3: nums[3]=3, swap with slow=1. Array: [1, 3, 0, 0, 12]
  5. 5fast=4: nums[4]=12, swap with slow=2. Array: [1, 3, 12, 0, 0]

Edge Cases for Move Zeroes

Edge cases are straightforward but worth considering during interviews. If the array has no zeros, the fast and slow pointers advance together and every element swaps with itself — effectively a no-op. The array remains unchanged.

If the array is all zeros, the fast pointer never finds a non-zero value, so slow never advances. No swaps occur and the array stays as-is, which is already correct since all zeros are already at the end (there is nothing else).

A single-element array is trivially correct regardless of whether it is zero or non-zero. An already-sorted array like [1, 2, 3, 0, 0] also works — the pointers move in lockstep through the non-zero prefix, then fast scans the trailing zeros without triggering any swaps.

  • No zeros: pointers move together, array unchanged
  • All zeros: no swaps occur, array already correct
  • Single element: trivially correct
  • Already sorted: pointers advance in lockstep through non-zero prefix
⚠️

Common Mistake

Don't create a new array — the problem requires in-place modification. The two-pointer swap approach modifies the original array with O(1) extra space.

What Move Zeroes Teaches You

Move Zeroes is more than just an Easy warm-up. It teaches the same-direction two-pointer partition pattern that appears throughout array problems. Once you internalize slow-tracks-placement and fast-scans-ahead, you can apply it to Remove Duplicates (#26), Remove Element (#27), and Sort Colors (#75) with only minor adjustments.

The key insight is that partitioning an array in-place is always the same mechanic: one pointer decides where to place the next valid element, the other pointer finds the next valid element. What changes between problems is the definition of valid.

If you are preparing for coding interviews, make Move Zeroes one of your first solves. Practice it until the two-pointer swap is automatic, then move on to the harder variations. YeetCode flashcards can help you drill this pattern through spaced repetition so the technique stays fresh when interview day arrives.

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now