LeetCode 283: Move Zeroes - All Solutions Explained

Problem Statement

Section link icon

The Move Zeroes problem (LeetCode 283) is an easy-level array manipulation challenge where you need to move all zeros in an array to the end while maintaining the relative order of non-zero elements.

Constraints

- 1 ≤ nums.length ≤ 10⁴

- -2³¹ ≤ nums[i] ≤ 2³¹ - 1

- Must do this in-place without making a copy of the array

Example

Input: nums = [0,1,0,3,12]
Output: [1,3,12,0,0]
## Understanding the Problem Key insights: 1. Need to preserve the order of non-zero elements 2. Must perform operations in-place (O(1) space) 3. The solution should be efficient for large arrays 4. Multiple approaches exist with different characteristics ## Solution 1: Two Pointers (Optimal Solution)

Explanation of the Best Solution

This approach uses two pointers to separate zero and non-zero elements:

  1. Initialize Pointer: non_zero_index = 0
  2. First Pass:
  3. Iterate through array with i
  4. When nums[i] != 0, copy to nums[non_zero_index] and increment
  5. Second Pass:
  6. Fill remaining positions from non_zero_index to end with zeros

Step-by-Step Example

For nums = [0,1,0,3,12]: 1. i=0: 0 → skip 2. i=1: 1 → copy to pos 0 → [1,1,0,3,12], non_zero_index=1 3. i=2: 0 → skip 4. i=3: 3 → copy to pos 1 → [1,3,0,3,12], non_zero_index=2 5. i=4: 12 → copy to pos 2 → [1,3,12,3,12], non_zero_index=3 6. Fill zeros from index 3 → [1,3,12,0,0]

Python Code (Two Pointers Solution)

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        non_zero_index = 0

        # Move all non-zero elements to front
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[non_zero_index] = nums[i]
                non_zero_index += 1

        # Fill remaining with zeros
        for i in range(non_zero_index, len(nums)):
            nums[i] = 0

# Test case
nums = [0,1,0,3,12]
Solution().moveZeroes(nums)
print(nums)  # Output: [1,3,12,0,0]

Complexity

  • Time Complexity: O(n) - Two passes through array
  • Space Complexity: O(1) - In-place modification
  • Optimizations: Minimal operations, no extra space

Why It's the Best

  • Optimal O(n) time complexity
  • Minimal space usage (in-place)
  • Clear and easy to understand
  • Preserves element order perfectly

Solution 2: Snowball Approach (Alternative)

Section link icon

Explanation

This approach treats zeros as a snowball that grows as we push non-zeros forward:

  1. Track Snowball Size:
  2. Count consecutive zeros
  3. Swap Non-Zeros:
  4. When encountering non-zero, swap with first zero in snowball
  5. Result:
  6. Zeros get pushed to end through swaps

Step-by-Step Example

For nums = [0,1,0,3,12]: 1. i=0: snowball=1 2. i=1: swap nums[0] and nums[1] → [1,0,0,3,12], snowball=1 3. i=2: snowball=2 4. i=3: swap nums[1] and nums[3] → [1,3,0,0,12], snowball=2 5. i=4: swap nums[2] and nums[4] → [1,3,12,0,0]

Python Code (Snowball Solution)

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        snowball = 0
        for i in range(len(nums)):
            if nums[i] == 0:
                snowball += 1
            elif snowball > 0:
                nums[i - snowball], nums[i] = nums[i], 0  # Swap with first zero

# Test case
nums = [0,1,0,3,12]
Solution().moveZeroes(nums)
print(nums)  # Output: [1,3,12,0,0]

Complexity

  • Time Complexity: O(n) - Single pass
  • Space Complexity: O(1) - In-place swaps
  • Best for: When minimal writes are important

Pros and Cons

  • Pros: Single pass, elegant swapping
  • Cons: More swaps than two-pointer approach
  • Variation: Can track first zero position instead of snowball size

Solution 3: Pythonic Approach (Not In-Place)

Section link icon

Explanation

This non-in-place solution demonstrates Python's capabilities but violates constraints:

  1. Filter and Count:
  2. Extract non-zeros
  3. Count zeros
  4. Combine:
  5. Extend with zeros
  6. Note: Not valid for LeetCode but good for understanding

Python Code (Non-In-Place)

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        non_zeros = [x for x in nums if x != 0]
        zeros = [0] * (len(nums) - len(non_zeros))
        nums[:] = non_zeros + zeros  # Only works if we can assign new list

# Test case
nums = [0,1,0,3,12]
Solution().moveZeroes(nums)
print(nums)  # Output: [1,3,12,0,0]

Complexity

  • Time Complexity: O(n) - But creates new lists
  • Space Complexity: O(n) - Extra space for new lists
  • When to Use: Not for LeetCode, but for quick Python solutions

Edge Cases to Consider

Section link icon
  • All zeros → array remains unchanged
  • No zeros → array remains unchanged
  • Single element array → no change needed
  • All non-zeros followed by zeros → already correct
  • Large input (10,000 elements) → verify performance

Final Thoughts

Section link icon
  • Two Pointers: Best for most cases (optimal and clear)
  • Snowball: Elegant single-pass alternative
  • Pythonic: Demonstrates language features but invalid
  • Key Insight: Tracking write position is crucial

For further practice, try similar problems like Remove Element (LeetCode 27) or Remove Duplicates from Sorted Array (LeetCode 26).