Editorial
Core insight
Move Zeroes · Two Pointers
Core Insight for Move Zeroes
The key intuition for the optimal LeetCode 283 Solution is to decouple the act of finding a non-zero element from the act of placing it.
We can maintain a pointer, let's call it write_pointer, that indicates the index where the next non-zero element belongs. As we iterate through the array with a read_pointer, every time we encounter a non-zero element, we know it belongs at the write_pointer's position.
The Invariant:
At any step of the iteration, the subarray nums[0...write_pointer-1] contains all processed non-zero elements in their correct relative order.
By swapping the non-zero element found at read_pointer with the element at write_pointer, we achieve two things simultaneously:
- The non-zero element moves to the "consolidated" section at the front.
- The zero (if
write_pointerwas pointing to one) or the placeholder moves toward the end.
Visual Description:
Imagine the array is divided into two logical regions by the write_pointer:
- Stable Region (Left): Contains strictly non-zero elements in correct order.
- Unexplored/Mixed Region (Right): Contains zeros and non-zeros that haven't been compacted yet.
As the read_pointer scans right, the write_pointer only advances when a non-zero is locked into the Stable Region. If the array has no zeros, both pointers move together. If zeros exist, the read_pointer moves ahead, creating a gap between the two pointers that represents the accumulated zeros.

Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 283: Move Zeroes Solution & Explanation
Problem Overview
TL;DR: Use a "write pointer" to consolidate all non-zero elements at the beginning of the array, then fill the remaining positions with zeros (or swap elements to achieve the same effect in one pass).
The LeetCode 283 problem, titled Move Zeroes, asks us to manipulate an integer array nums. The objective is to shift all occurrences of 0 to the end of the array. Crucially, the relative order of the non-zero elements must remain unchanged. This operation must be performed in-place, meaning we cannot allocate a new array to store the result; we must modify the input array directly with extra space.
Brute Force Approach for Move Zeroes
A naive approach to solving Move Zeroes usually involves prioritizing the logic over the space constraints. One might attempt to create a temporary array to store the result.
Naive Algorithm:
- Initialize a new empty array,
result, of the same size asnums. - Iterate through
nums. If an element is non-zero, append it toresult. - Count the number of zeros encountered or simply fill the remaining slots in
resultwith zeros after the loop. - Copy
resultback intonums.
Pseudo-code:
function moveZeroesNaive(nums):
tempArray = []
zeroCount = 0
for x in nums:
if x != 0:
tempArray.append(x)
else:
zeroCount++
while zeroCount > 0:
tempArray.append(0)
zeroCount--
nums = tempArray // Copy backWhy this fails: While this solution produces the correct output, it violates the problem's strict constraint: "do this in-place without making a copy of the array."
- Time Complexity: , where is the number of elements.
- Space Complexity: due to the temporary array. This makes the solution suboptimal for memory-constrained environments and invalid according to the problem statement.
Another brute force variation involves using nested loops (similar to Bubble Sort) to "bubble" zeros to the end one by one. This satisfies the space constraint but results in time complexity, which is inefficient for large inputs ().
Algorithm Strategy: Two Pointer Patterns
- Initialization: Initialize a variable
write_pointer(often calledlastNonZeroFoundAt) to 0. This tracks the position where the next non-zero value should be written. - Iteration: Start a loop with a variable
read_pointer(usually the loop indexi) iterating from 0 to the end of the array. - Condition Check: Inside the loop, check if
nums[read_pointer]is non-zero. - Swap and Advance:
- If
nums[read_pointer]is non-zero, swap the values atnums[write_pointer]andnums[read_pointer]. - Increment
write_pointer. - (If
nums[read_pointer]is zero, do nothing; just let theread_pointercontinue).
- If
- Completion: Once the
read_pointerfinishes the array, all non-zeros are compacted at the start, and all zeros have been implicitly moved to the end via the swaps.
Note: An alternative implementation is to copy non-zeros to write_pointer and then fill the remaining indices with 0 in a separate loop. The swap method is generally preferred as it handles the "minimize operations" follow-up more elegantly.
Execution Flow
Let's trace nums = [0, 1, 0, 3, 12]
- Start:
write_pointer = 0,read_pointer = 0. - i = 0:
nums[0]is0.- Condition fail.
write_pointerstays at 0.
- Condition fail.
- i = 1:
nums[1]is1.- Condition pass (
1 != 0). - Swap
nums[write_pointer](index 0) andnums[read_pointer](index 1). - Array becomes
[1, 0, 0, 3, 12]. - Increment
write_pointerto 1.
- Condition pass (
- i = 2:
nums[2]is0.- Condition fail.
write_pointerstays at 1.
- Condition fail.
- i = 3:
nums[3]is3.- Condition pass (
3 != 0). - Swap
nums[1](value 0) andnums[3](value 3). - Array becomes
[1, 3, 0, 0, 12]. - Increment
write_pointerto 2.
- Condition pass (
- i = 4:
nums[4]is12.- Condition pass (
12 != 0). - Swap
nums[2](value 0) andnums[4](value 12). - Array becomes
[1, 3, 12, 0, 0]. - Increment
write_pointerto 3.
- Condition pass (
- End: Loop finishes. Result is
[1, 3, 12, 0, 0].
Proof of Correctness
The algorithm is correct based on the Loop Invariant:
At the start of each iteration i, the subarray nums[0...write_pointer-1] consists of all non-zero elements found in nums[0...i-1], in their original relative order.
- Initialization: Before the loop,
write_pointeris 0. The subarray is empty, vacuously satisfying the property. - Maintenance: When
nums[i]is non-zero, we move it tonums[write_pointer]. Sincewrite_pointeris the first available slot after the previously processed non-zeros, the relative order is preserved. We then incrementwrite_pointerto maintain the invariant. - Termination: When
ireaches ,nums[0...write_pointer-1]contains all non-zeros from the entire array. The remaining elements (fromwrite_pointerto ) must be zeros because every time we found a non-zero, we moved it out of that area (via swap) or it was already in the correct place.
Pattern Reuse Notes
The Two Pointers - In-place Array Modification pattern is a fundamental technique for array manipulation. Understanding the logic of write_pointer vs read_pointer enables you to solve several related interview questions efficiently:
- LeetCode 26: Remove Duplicates from Sorted Array - Uses the exact same logic, but the condition checks for uniqueness rather than non-zero values.
- LeetCode 27: Remove Element - Identical structure; instead of moving zeros, you overwrite a specific target value.
- LeetCode 75: Sort Colors - A more complex variation involving three pointers (low, mid, high) to sort 0s, 1s, and 2s in-place.
- LeetCode 80: Remove Duplicates from Sorted Array II - Extends the pattern to allow at most two duplicates, requiring slightly more complex pointer logic.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 283
1class Solution {
2public:
3 void moveZeroes(vector<int>& nums) {
4 int writePtr = 0;
5
6 // Iterate through the array with a read pointer (i)
7 for (int readPtr = 0; readPtr < nums.size(); readPtr++) {
8 // If the current element is non-zero
9 if (nums[readPtr] != 0) {
10 // Swap the non-zero element to the write position
11 // This handles both moving non-zeros to front
12 // and zeros to back simultaneously.
13 swap(nums[writePtr], nums[readPtr]);
14 writePtr++;
15 }
16 }
17 }
18};Java Solution for LeetCode 283
1class Solution {
2 public void moveZeroes(int[] nums) {
3 int writePtr = 0;
4
5 // Iterate through the array
6 for (int readPtr = 0; readPtr < nums.length; readPtr++) {
7 // If we find a non-zero element
8 if (nums[readPtr] != 0) {
9 // Swap the current element with the element at writePtr
10 int temp = nums[writePtr];
11 nums[writePtr] = nums[readPtr];
12 nums[readPtr] = temp;
13
14 // Advance the write pointer
15 writePtr++;
16 }
17 }
18 }
19}Python Solution for LeetCode 283
1class Solution:
2 def moveZeroes(self, nums: List[int]) -> None:
3 """
4 Do not return anything, modify nums in-place instead.
5 """
6 write_ptr = 0
7
8 for read_ptr in range(len(nums)):
9 if nums[read_ptr] != 0:
10 # Pythonic swap to move non-zero to the front
11 nums[write_ptr], nums[read_ptr] = nums[read_ptr], nums[write_ptr]
12 write_ptr += 1