Move Zeroes Solution
Given an integer array nums, move all 0's to the end while maintaining the relative order of the non-zero elements. Do this in-place.
Problem Statement
Given an integer array nums, move all 0's 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.
Brute Force β Extra Array O(n)
Create a new array. First copy all non-zero elements, then fill the rest with zeros. Copy back to the original. Correct but violates the in-place constraint.
| Metric | Value |
|---|---|
| Time | O(n) |
| Space | O(n) β violates in-place requirement |
Read/Write Pointer β O(n) time, O(1) space
Use a write pointer that tracks where the next non-zero should go. A read pointer scans the array. When the reader finds a non-zero value, swap it into the writer's position and advance both. Zeros naturally accumulate at the end.
- Step 1: Initialize
write = 0. - Step 2: For each
readfrom 0 to nβ1: ifnums[read] β 0, swapnums[write]andnums[read], thenwrite++. - Step 3: After the loop, all non-zeros are compacted to positions 0..writeβ1, and zeros fill write..nβ1.
- Any problem asking to partition or compact an array in-place β move certain elements to one side, remove duplicates (LC 26), or segregate values.
- The signal is "rearrange in-place preserving relative order." The read/write (or slow/fast) pointer pattern appears in LC 283, LC 26 (Remove Duplicates), LC 27 (Remove Element), and LC 75 (Sort Colors).
Visual Walkthrough
Trace through nums = [0, 1, 0, 3, 12]:
Code β Java & Python
Complexity Analysis
| Approach | Time | Space | Trade-off |
|---|---|---|---|
| Extra Array | O(n) | O(n) | Simple but violates in-place constraint |
| Two-pass (compact + fill) | O(n) | O(1) | First pass moves non-zeros, second fills zeros |
| Swap β optimal | O(n) | O(1) | Single pass, in-place swap. Minimizes writes. |
Edge Cases & Pitfalls
| Case | Input | Why It Matters |
|---|---|---|
| No zeros | [1, 2, 3] | Write follows read exactly β array unchanged. Zero swaps with itself. |
| All zeros | [0, 0, 0] | Write never advances β all elements stay zero. |
| Single element | [0] or [5] | Trivial β nothing to move. |
| Zeros at end | [1, 2, 0, 0] | Already in correct position β write catches up, self-swaps. |
| Negative numbers | [0, -1, 0, -3] | Negatives are non-zero β treated like any other value. |
nums[write] = nums[read] without zeroing nums[read]. This leaves the original non-zero in place, creating duplicates. Always swap β or use a two-pass approach where you fill zeros explicitly after compacting.