How to Move All Zeros to the End of an Array in Java

Moving all zeros to the end of an array is one of the most frequently asked array problems in Java interviews. The challenge is not simply moving the zeros, but doing so while preserving the relative order of the non-zero elements.

Although using an extra array is straightforward, interviewers usually expect an in-place solution that uses the two-pointer technique. This approach achieves O(n) time complexity with O(1) extra space.

In this tutorial, you'll learn both approaches, understand how they work internally, and discover why the two-pointer method is considered the optimal solution.

Advertisement

Problem Statement

Given the following array:

int[] numbers = {0, 1, 0, 3, 12};

Move all zeros to the end while preserving the order of the remaining elements.

Before

[0, 1, 0, 3, 12]

After

[1, 3, 12, 0, 0]
 

Method 1: Using an Extra Array

One simple solution is to create another array and copy all non-zero elements into it. Since Java initializes integer arrays with zeros by default, the remaining positions automatically stay as zero.

Example

 
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {

        int[] numbers = {0, 1, 0, 3, 12};

        int[] result = new int[numbers.length];

        int index = 0;

        for (int num : numbers) {

            if (num != 0) {
                result[index++] = num;
            }
        }

        System.out.println(Arrays.toString(result));
    }
}
 

Output

 
[1, 3, 12, 0, 0]
 

Explanation

The algorithm works as follows:

  1. Create a new array of the same size.
  2. Traverse the original array.
  3. Copy only the non-zero elements into the new array.
  4. The remaining positions automatically remain zero.

Time Complexity: O(n)

Space Complexity: O(n)

Although easy to understand, this solution requires additional memory.


Method 2: Two-Pointer In-Place Technique (Optimal)

The optimal solution modifies the original array without creating another array.

It uses two pointers:

  • One pointer scans every element.
  • The other tracks where the next non-zero element should be placed.

Example

 
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {

        int[] numbers = {0, 1, 0, 3, 12};

        int insertPosition = 0;

        for (int i = 0; i < numbers.length; i++) {

            if (numbers[i] != 0) {

                numbers[insertPosition] = numbers[i];
                insertPosition++;
            }
        }

        while (insertPosition < numbers.length) {

            numbers[insertPosition] = 0;
            insertPosition++;
        }

        System.out.println(Arrays.toString(numbers));
    }
}
 

Output

[1, 3, 12, 0, 0]

Explanation

The algorithm performs two passes:

  1. Move every non-zero element to the front of the array.
  2. Fill the remaining positions with zeros.

This preserves the original order of the non-zero elements while using only constant extra memory.

Time Complexity: O(n)

Space Complexity: O(1)


Step-by-Step Explanation

Consider the array:

 
[0, 1, 0, 3, 12]
 

Initially:

 
insertPosition = 0
 

Step 1

 
i = 0

numbers[0] = 0
 

Zero is ignored.

Array remains:

 
[0, 1, 0, 3, 12]
 

Step 2

 
i = 1

numbers[1] = 1
 

Move it to position 0.

 
[1, 1, 0, 3, 12]
 

Update:

 
insertPosition = 1
 

Step 3

 
i = 2

numbers[2] = 0
 

Skip it.


Step 4

 
i = 3

numbers[3] = 3
 

Move it.

 
[1, 3, 0, 3, 12]
 

Update:

 
insertPosition = 2
 

Step 5

 
i = 4

numbers[4] = 12
 

Move it.

 
[1, 3, 12, 3, 12]
 

Update:

 
insertPosition = 3
 

Step 6

Fill the remaining positions with zeros.

 
numbers[3] = 0
numbers[4] = 0
 

Final array:

 
[1, 3, 12, 0, 0]
 

Internal Working

Initial array:

 
[0, 1, 0, 3, 12]
 

After processing non-zero values:

 
[1, 3, 12, 3, 12]
 

Notice that the last two values are duplicates because the original values haven't been cleared yet.

After filling zeros:

 
[1, 3, 12, 0, 0]
 

Only two integer variables (i and insertPosition) are used throughout the algorithm.


Real-Life Analogy

Imagine a conveyor belt carrying both filled and empty boxes.

Your task is to move all filled boxes to the front while keeping them in the same order.

As you walk along the conveyor belt:

  • Every filled box is placed into the next available front position.
  • Empty boxes are ignored.
  • After all filled boxes have been moved, every remaining position is marked as empty.

This is exactly how the two-pointer algorithm works.


Best Practices

  • Use the two-pointer technique whenever an in-place solution is required.
  • Preserve the relative order of non-zero elements.
  • Test arrays containing only zeros.
  • Test arrays containing no zeros.
  • Test single-element and empty arrays.

Common Mistakes

1. Not Preserving the Order

Incorrect solutions sometimes rearrange the non-zero elements.

The original order should always remain unchanged.


2. Forgetting to Fill Remaining Positions

After moving non-zero values, always fill the remaining positions with zeros.

Otherwise, duplicate values remain at the end.


3. Using Extra Space Unnecessarily

Creating another array works but increases the space complexity from O(1) to O(n).


4. Removing Zeros Instead of Moving Them

The array length should remain exactly the same.

Zeros must be moved—not removed.


Expert Tips

  • The read-pointer/write-pointer technique is useful in many array problems.
  • The same approach can move any specific value—not just zero—to the end.
  • This pattern is also used in problems such as removing duplicates from sorted arrays and partitioning arrays.
  • Understanding this technique will make learning more advanced partitioning algorithms much easier.

Comparison Table

Method Time Complexity Space Complexity Preserves Order?
Extra Array O(n) O(n) ✅ Yes
Two-Pointer In-Place O(n) O(1) ✅ Yes (Optimal)

Frequently Asked Questions

1. What is the best way to move zeros to the end of an array?

The two-pointer in-place technique is the optimal solution because it runs in O(n) time while using O(1) extra space.


2. Does moving zeros change the array size?

No. The array length remains exactly the same. Only the positions of the elements change.


3. Is preserving the order of non-zero elements important?

Yes. Most interview questions require the original relative order of the non-zero elements to remain unchanged.


4. What happens if the array contains no zeros?

The algorithm still works correctly. Every element remains in its original position, and the second loop does nothing.


5. What if every element is zero?

The first loop skips every element, and the second loop simply writes zeros back into the array. The result remains unchanged.


6. How is this different from removing zeros?

Removing zeros changes the effective size of the collection, while this problem keeps the array length unchanged by moving zeros to the end.


7. Can this technique move any specific value to the end?

Yes. Replace the condition:

numbers[i] != 0

with a check for the value you want to move.


8. Can I move zeros to the beginning using a similar technique?

Yes. The same two-pointer concept can be adapted to move zeros to the beginning by traversing the array differently and adjusting the write position.