Move Zeroes in Java DSA: Brute Force, Extra Array, and the Two Pointer Trick

  • Last Updated: July 16, 2026
  • By: javahandson
  • Series
img

Move Zeroes in Java DSA: Brute Force, Extra Array, and the Two Pointer Trick

Learn Move Zeroes in Java DSA with a beginner friendly guide. Compare brute force, an extra array, and the two pointer trick with a full dry run.

1. Introduction

Move Zeroes in Java DSA is a small problem with a big lesson hiding inside. You have probably seen it on LeetCode and thought it was easy. The catch shows up when someone asks you to do it without a second array.

Here is the task in plain words. You get an array of numbers. Some of them are zeroes. Push every zero to the end, and keep the other numbers in their original order. One more rule matters most: change the array in place.

In the last article we used Kadane’s Algorithm to sweep an array once and track a running best. Now we sweep again, but this time we move values instead of sums. We start with brute force, try a second array, then land on the two pointer version that interviewers really want.

2. Understanding the Problem

Let us pin down the rules first. Clear rules save you from silly bugs later.

  • You get an array of integers, for example [0, 1, 0, 3, 12].
  • Every zero must end up at the back of the array.
  • The non-zero numbers must keep their original relative order.
  • You must edit the array in place, so you return nothing.

For [0, 1, 0, 3, 12] the answer is [1, 3, 12, 0, 0]. Notice that 1 still comes before 3, and 3 still comes before 12. That ordering rule is the whole difficulty. Without it, you could just swap zeroes with the last element and finish in seconds.

💡 Interview Insight
Many people miss the words in place. If you build a fresh array and return it, you solved a different problem. Say the phrase out loud during the interview so they know you caught it.

3. Concepts You Need Here

Two small ideas carry this whole problem. Both come back in many array questions, so learn them once and reuse them forever.

3.1 In-Place Editing

In place means you work inside the array you already have. You do not allocate a second array of the same size. Your extra memory stays constant, no matter how big the input grows. So you write values over old slots instead of copying them somewhere new.

3.2 The Two Pointer Idea

Here two indexes walk the same array with different jobs. One index reads every value, front to back. The other index marks the slot where the next non-zero number belongs. Because the writer moves slower than the reader, it never overwrites a value you still need.

4. Approach 1: Brute Force with Shifting

The first idea most beginners reach for feels natural. Find a zero, then slide everything after it one step left, and drop a zero at the end. Repeat until no zero sits out of place.

4.1 Pseudocode

count = 0                  // zeroes already parked at the end
i = 0
while i < n - count:
    if nums[i] == 0:
        shift every element after i one step left
        nums[n-1] = 0
        count = count + 1  // one more zero parked
    else:
        i = i + 1          // only move on when no shift happened

The count variable tracks how many zeroes already sit at the back. We stop before them, otherwise we would shift the same zeroes forever. Also notice that we do not move i after a shift, because a brand new value just landed at that index.

4.2 Java Code

public class MoveZeroesBrute {
    public static void moveZeroes(int[] nums) {
        int n = nums.length;
        int count = 0;
        int i = 0;
        while (i < n - count) {
            if (nums[i] == 0) {
                for (int j = i; j < n - 1; j++) {
                    nums[j] = nums[j + 1];
                }
                nums[n - 1] = 0;
                count++;
            } else {
                i++;
            }
        }
    }
 
    public static void main(String[] args) {
        int[] nums = { 0, 1, 0, 3, 12 };
        moveZeroes(nums);
        System.out.println(java.util.Arrays.toString(nums)); // [1, 3, 12, 0, 0]
    }
}

4.3 Why This Works, Step by Step

Let us walk the code slowly. Every line has one clear job.

  • The variable i reads the array from left to right.
  • When nums[i] is a zero, the inner loop drags every later value one slot left.
  • That shift leaves a free slot at the very end, so we drop a zero there.
  • We bump count, because one more zero now sits safely at the back.
  • If nums[i] is not zero, we simply step forward with i++.

This solution edits the array in place, so it respects the main rule. Sadly it does a lot of repeated work, which we fix next.

4.4 Dry Run of the Brute Force

Let us trace nums = [0, 1, 0, 3, 12] by hand. First, here is what each column means, so nothing feels cryptic.

  • i (read index) is the position the outer loop is looking at right now.
  • nums[i] (value there) is the number sitting at that position.
  • count (zeroes parked) is how many zeroes already sit safely at the back.

Watch two things as you read. The i column only moves forward when no shift happened. The count column grows by one every time we park a zero.

Stepi (read index)nums[i] (value there)ActionArray aftercount (zeroes parked)
100Shift left, park a zero at the end[1, 0, 3, 12, 0]1
201Not zero, so move i forward[1, 0, 3, 12, 0]1
310Shift left, park a zero at the end[1, 3, 12, 0, 0]2
413Not zero, so move i forward[1, 3, 12, 0, 0]2
5212Not zero, so move i forward[1, 3, 12, 0, 0]2

Look at step one and step two together. After the shift, i stayed at 0 on purpose. A fresh value, the 1, had just slid into that slot, so we had to inspect it before moving on.

Now check why the loop stops after step five. Here n is 5 and count is 2, so the guard reads i < 3. Since i has climbed to 3, the loop ends. We never look at index 3 or 4 again, because both hold zeroes we parked ourselves.

Count the work too. Two zeroes meant two full shifts of the tail. On a big array with many zeroes, that repeated dragging is exactly what makes this approach crawl.

4.5 Time and Space Cost

Each zero can trigger a full shift of the array. With many zeroes, that becomes n shifts of n elements. So the time lands at O(n squared). The space stays O(1), since we only keep a few counters. For a tiny array nobody notices. For a large one it crawls.

5. Approach 2: Using an Extra Array

Here is a cleaner idea. Walk the array once and copy every non-zero value into a fresh array. Then fill whatever space is left with zeroes. Finally copy the result back into the original array.

5.1 Pseudocode

temp = new array of size n     // starts full of zeroes in Java
k = 0
for each num in nums:
    if num != 0:
        temp[k] = num
        k = k + 1
copy temp back into nums

5.2 Java Code

public class MoveZeroesExtraArray {
    public static void moveZeroes(int[] nums) {
        int[] temp = new int[nums.length];
        int k = 0;
        for (int num : nums) {
            if (num != 0) {
                temp[k] = num;
                k++;
            }
        }
        for (int i = 0; i < nums.length; i++) {
            nums[i] = temp[i];
        }
    }
 
    public static void main(String[] args) {
        int[] nums = { 0, 1, 0, 3, 12 };
        moveZeroes(nums);
        System.out.println(java.util.Arrays.toString(nums)); // [1, 3, 12, 0, 0]
    }
}

5.3 Reading the Code

  • First we build temp, a new array of the same length. Java fills it with zeroes for free.
  • Then we walk nums and copy only the non-zero values into temp, packed from the left.
  • Because we copy them in order, the relative order survives untouched.
  • The tail of temp is still zeroes, so the zeroes land at the back automatically.
  • Last, we copy temp back into nums, which keeps the caller’s array reference valid.

Time drops to O(n), which is a real win. But space climbs to O(n), and the whole point of the problem was to avoid that. An interviewer will push back here almost every time.

5.4 Dry Run of the Extra Array

This trace is the easiest of the three. We read nums from left to right and only care about the non-zero values. Remember that Java hands us temp already filled with zeroes.

StepValue readZero?Actiontemp afterk (next free slot)
10YesSkip it, write nothing[0, 0, 0, 0, 0]0
21NoCopy 1 into temp[0][1, 0, 0, 0, 0]1
30YesSkip it, write nothing[1, 0, 0, 0, 0]1
43NoCopy 3 into temp[1][1, 3, 0, 0, 0]2
512NoCopy 12 into temp[2][1, 3, 12, 0, 0]3

Notice that we never wrote a single zero ourselves. The zeroes at index 3 and index 4 were already there when Java built the array. That free head start is what makes this version so short.

The last step copies temp back into nums, so the caller sees [1, 3, 12, 0, 0]. Compare this trace with the brute force one above. Same answer, five steps instead of five plus two full shifts, but we paid for a whole second array to get it.

💡 Interview Insight
Mentioning this approach still earns points. It shows you can reach O(n) time quickly. Just say the space cost out loud yourself, then offer to remove it. Naming your own trade-off reads as confidence, not weakness.

6. Approach 3: The Two Pointer Trick

Now for the version interviewers want. The trick is to stop thinking about moving zeroes at all. Instead, think about pulling the non-zero values forward. The zeroes then sort themselves out.

Keep one index called insert. It marks the slot where the next non-zero value belongs. Walk the array with a second index. Every time you meet a non-zero number, write it at insert and bump insert forward. When the walk ends, every slot from insert onward gets a zero.

6.1 Pseudocode

insert = 0
for each num in nums:
    if num != 0:
        nums[insert] = num
        insert = insert + 1
for i from insert to n-1:
    nums[i] = 0

6.2 Java Code

public class MoveZeroesTwoPointer {
    public static void moveZeroes(int[] nums) {
        int insert = 0;
        for (int num : nums) {
            if (num != 0) {
                nums[insert] = num;
                insert++;
            }
        }
        while (insert < nums.length) {
            nums[insert] = 0;
            insert++;
        }
    }
 
    public static void main(String[] args) {
        int[] nums = { 0, 1, 0, 3, 12 };
        moveZeroes(nums);
        System.out.println(java.util.Arrays.toString(nums)); // [1, 3, 12, 0, 0]
    }
}

6.3 Reading the Code Line by Line

This version does the most thinking, so let us break it apart gently.

  • We start insert at 0, because the first non-zero value belongs at the very front.
  • The first loop reads every number once. There is no inner loop, which is the whole point.
  • When a number is not zero, we write it at nums[insert] and push insert one step ahead.
  • Zeroes get skipped silently. We never write them, so they simply fall behind.
  • After the loop, insert equals the count of non-zero values. Everything from there on must become a zero.
  • The second loop fills that tail with zeroes and finishes the job.

Here is the part that trips people up. Does the write at nums[insert] destroy a value we still need? It cannot. The insert index never runs ahead of the reader, so any slot we overwrite was already read.

💡 Interview Insight
A common follow-up asks why we do not swap instead of overwrite. Swapping also works and keeps the same Big-O. Overwriting is simpler to explain, though swapping does fewer total writes when zeroes are rare. Either answer is fine if you can defend it.

7. Dry Run of the Two Pointer Approach

We traced the other two approaches already, so let us give this one the same treatment. Follow the same input, nums = [0, 1, 0, 3, 12]. Watch how insert crawls forward while the reader races ahead.

Stepnum readZero?ActionArray afterinsert (next slot)
10YesSkip it, write nothing[0, 1, 0, 3, 12]0
21NoWrite 1 at index 0[1, 1, 0, 3, 12]1
30YesSkip it, write nothing[1, 1, 0, 3, 12]1
43NoWrite 3 at index 1[1, 3, 0, 3, 12]2
512NoWrite 12 at index 2[1, 3, 12, 3, 12]3

Look at step five closely. The array now reads [1, 3, 12, 3, 12], which looks wrong at a glance. Do not panic. The values at index 3 and index 4 are leftover junk, and the reader has already passed them. Since insert is 3, the second loop overwrites both with zeroes.

Fill stepIndexActionArray after
13Write a zero[1, 3, 12, 0, 12]
24Write a zero[1, 3, 12, 0, 0]

The final array is [1, 3, 12, 0, 0]. Every zero sits at the back, and 1, 3, and 12 kept their original order. We touched each slot at most twice, and we never built a second array.

7.1 The Same Dry Run on Paper

move zeroes in java dsa

The sketch above shows the same trace. Phase one pulls the non-zero values forward, and the shaded cells show the part of the array that is already settled. Phase two fills the tail with zeroes. Many people find this picture easier than the table, so use whichever clicks for you.

8. Comparing the Three Approaches

All three approaches give the right answer. They just pay different prices. Here is the plain comparison.

ApproachTimeSpaceNote
Brute force shiftingO(n squared)O(1)In place, but slow when zeroes are common
Extra arrayO(n)O(n)Fast and simple, breaks the in-place rule
Two pointerO(n)O(1)Fast and in place, the answer they want

In an interview, walk this exact path. Start with brute force to prove you understand the problem. Bring up the extra array to show you can hit O(n) time. Then remove the extra array with two pointers. That climb from slow to clean is what interviewers grade you on.

9. Common Mistakes and Edge Cases

A few small traps catch beginners on this problem. Keep these in mind.

  • An empty array or an array with one element needs no work. All three approaches handle it naturally.
  • An array of all zeroes ends up unchanged, since insert stays at 0 and the fill loop rewrites zeroes.
  • An array with no zeroes at all rewrites every value onto itself, which is harmless.
  • Never sort the array to push zeroes back. Sorting destroys the original order of the other numbers.
  • Do not forget the second loop. Without it you leave junk values in the tail, like that stray [1, 3, 12, 3, 12].
  • Negative numbers work fine. Only a value equal to zero gets skipped.

10. Interview Questions

Q: What is the Move Zeroes problem in Java?

A: You get an array of integers and must push every zero to the end while keeping the non-zero numbers in their original relative order. The array must be changed in place, so you return nothing.

Q: What is the most efficient way to solve Move Zeroes in Java?

A: The two pointer approach is best. Keep an insert index for the next non-zero slot, walk the array once writing every non-zero value at insert, then fill the rest with zeroes. That gives O(n) time and O(1) extra space.

Q: Why can I not just sort the array to move zeroes to the end?

A: Sorting reorders the non-zero numbers too, which breaks the main rule. The problem requires that values like 1, 3, and 12 keep their original relative order.

Q: Does the two pointer approach overwrite values I still need?

A: No. The insert index never runs ahead of the reading index, so any slot you overwrite was already read. Leftover junk in the tail gets replaced with zeroes in the second loop.

Q: What is the time complexity of Move Zeroes in Java?

A: Brute force shifting runs in O(n squared) time with O(1) space. The extra array approach runs in O(n) time but uses O(n) space. The two pointer approach runs in O(n) time with O(1) space.

Q: Should I swap or overwrite in the two pointer solution?

A: Both work and share the same Big-O. Overwriting is easier to explain, while swapping does fewer total writes when zeroes are rare. Either is fine in an interview if you can defend the choice.

11. Conclusion

Move Zeroes in Java looks like a beginner warm-up, and in a way it is. But the two pointer idea inside it is a real skill. You will reuse that slow-writer and fast-reader pattern in Remove Duplicates, Remove Element, and many string problems.

So take the pattern, not just the answer. Try brute force first when you feel stuck. Reach for an extra array when you want speed fast. Then squeeze out the extra memory with two pointers. Once that move feels natural, a whole family of array problems opens up for you.

12. What’s Next

You now have Move Zeroes in your toolkit, so let us keep the momentum going. Here is where you came from and where you head next in this series.

13. Further Reading

Leave a Comment