Move Zeros to End

Java coding interview problem for Array Logic: Move Zeros to End.

Moving all zeros to the end of an array is one of the most frequently asked array interview problems.

Although the problem looks simple, it tests important concepts:

  • Array traversal
  • Two Pointer Technique
  • In-place modification
  • Stable ordering
  • Space optimization
  • Algorithm design

This problem is a foundation for many advanced problems:

  • Remove duplicates from array
  • Partition array
  • Move negative numbers
  • Sliding window problems
  • Data transformation

What Does Moving Zeros Mean?

Given an array, move all zero values to the end while maintaining the relative order of all non-zero elements.


Example

Input:

[0,1,0,3,12]

Output:

[1,3,12,0,0]

Explanation:

Non-zero elements:

1,3,12

remain in the same order.

Zeros move to the end.


Another Example

Input:

[5,0,2,0,8,1]

Output:

[5,2,8,1,0,0]

Why Is This Question Asked in Interviews?

Interviewers ask this problem because it evaluates:

  • Understanding of arrays
  • Ability to modify data in-place
  • Pointer manipulation
  • Memory optimization
  • Handling edge cases

Common interview variations:

  • Move zeros to beginning
  • Move negative numbers
  • Remove duplicates
  • Partition array around a value
  • Move all null values

Real-World Applications

Data Processing

Large datasets often contain empty or invalid values.

Example:

Before processing:

[100,0,200,0,300]

After cleanup:

[100,200,300,0,0]

Valid data is processed first.


Image Processing

Pixel arrays may contain empty pixels represented by:

0

Moving them allows efficient processing.


Database Processing

Missing values may be represented as:

0

Data transformation pipelines can move invalid values separately.


Memory Management

Compaction algorithms move unused spaces toward the end.


Problem Statement

Given an integer array,

move all zeros to the end while maintaining the relative order of non-zero elements.

The operation should be performed in-place if possible.


Example 1

Input:

[0,1,0,3,12]

Output:

[1,3,12,0,0]

Example 2

Input:

[1,2,3]

Output:

[1,2,3]

No zeros exist.


Example 3

Input:

[0,0,1]

Output:

[1,0,0]

Example 4

Input:

[0,0,0]

Output:

[0,0,0]

Understanding Zero Movement

Consider:

[0,5,0,3,8]

We need to separate:

Non-zero values:

5,3,8

Zeros:

0,0

Final:

[5,3,8,0,0]

Stable Movement

A stable algorithm keeps the original order of non-zero elements.

Example:

Input:

[4,0,2,7,0,9]

Stable output:

[4,2,7,9,0,0]

Order:

4 → 2 → 7 → 9

is preserved.


Unstable Movement

An unstable algorithm may change the order.

Example:

Possible output:

[9,2,7,4,0,0]

Zeros are moved, but original ordering is lost.

Most interview problems expect:

Stable movement

Array Visualization

Input:

Index:

0 1 2 3 4

0 1 0 3 12

Find non-zero elements:

1

3

12

Move them forward:

1 3 12

Fill remaining positions:

0 0

Final:

1 3 12 0 0

Dry Run

Input:

[0,1,0,3,12]

Initial:

result position = 0

Read:

0

Ignore.


Read:

1

Place at index 0:

[1,1,0,3,12]

Read:

0

Ignore.


Read:

3

Place at index 1:

[1,3,0,3,12]

Read:

12

Place at index 2:

[1,3,12,3,12]

Fill remaining:

[1,3,12,0,0]

Approach 1 — Using Extra Array (Beginner Friendly)

The easiest solution is creating a new array.

The idea:

  1. Copy all non-zero elements.
  2. Fill remaining positions with zeros.

Algorithm

  1. Create new array.
  2. Maintain an index.
  3. Traverse original array.
  4. Copy non-zero values.
  5. Remaining positions stay zero.

Java Program

import java.util.Arrays;

public class MoveZerosExtraSpace {


    public static int[] moveZeros(
            int[] numbers) {


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


        int index = 0;


        for (int number : numbers) {


            if (number != 0) {


                result[index++] = number;

            }

        }


        return result;

    }


    public static void main(String[] args) {


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


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

    }

}

Output

[1,3,12,0,0]

Step-by-Step Explanation

Input:

[0,1,0,3,12]

Create:

[0,0,0,0,0]

Read:

0

Skip.


Read:

1

Copy:

[1,0,0,0,0]

Read:

3

Copy:

[1,3,0,0,0]

Read:

12

Copy:

[1,3,12,0,0]

Complexity Analysis

Time:

O(n)

Every element is visited once.

Space:

O(n)

New array is created.


Advantages

  • Very easy to understand.
  • Maintains order.
  • Does not modify original array.
  • Good beginner approach.

Drawbacks

  • Requires extra memory.
  • Not ideal when memory is limited.
  • Not an in-place solution.

Approach 2 — Two Pointer Approach (Optimal)

The two pointer approach is the preferred interview solution.

It moves zeros without creating another array.


Two Pointer Concept

Use:

nonZeroIndex

to track where the next non-zero element should go.


Example:

Input:

[0,1,0,3,12]

Pointer:

nonZeroIndex = 0

Read:

1

Swap with index 0.

Result:

[1,0,0,3,12]

Read:

3

Swap with index 1.

Result:

[1,3,0,0,12]

Read:

12

Swap with index 2.

Result:

[1,3,12,0,0]

Algorithm

  1. Initialize pointer:
index = 0;
  1. Traverse array.
  2. Whenever non-zero value appears:
    • Swap with index.
    • Increment index.

Java Program

import java.util.Arrays;

public class MoveZerosTwoPointer {


    public static void moveZeros(
            int[] numbers) {


        int index = 0;


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


            if (numbers[i] != 0) {


                int temp =
                        numbers[index];


                numbers[index] =
                        numbers[i];


                numbers[i] =
                        temp;


                index++;

            }

        }

    }


    public static void main(String[] args) {


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


        moveZeros(numbers);


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

    }

}

Output

[1,3,12,0,0]

Step-by-Step Explanation

Input:

[0,1,0,3,12]

index:

0

i = 0:

Value:

0

Skip.


i = 1:

Value:

1

Swap:

index 0 ↔ i 1

Array:

[1,0,0,3,12]

Increase index:

1

i = 3:

Value:

3

Swap:

index 1 ↔ i 3

Array:

[1,3,0,0,12]

i = 4:

Value:

12

Swap:

index 2 ↔ i 4

Array:

[1,3,12,0,0]

Complexity Analysis

Time:

O(n)

Space:

O(1)

Advantages

  • Optimal solution.
  • In-place modification.
  • Maintains order.
  • Interview recommended.

Drawbacks

  • Slightly harder than extra array.
  • Modifies original array.

Approach 3 — Swap Optimization Approach

The two pointer approach can be slightly optimized.

Instead of always swapping values, we can:

  1. Move non-zero elements forward.
  2. Fill remaining positions with zeros.

This reduces unnecessary swaps.


Example

Input:

[0,1,0,3,12]

Move non-zero values:

[1,3,12,_,_]

Fill remaining:

[1,3,12,0,0]

Algorithm

  1. Maintain an index for placing non-zero values.
  2. Traverse the array.
  3. Copy non-zero values forward.
  4. Fill remaining positions with zero.

Java Program

import java.util.Arrays;

public class MoveZerosOptimized {


    public static void moveZeros(
            int[] numbers) {


        int index = 0;


        for (int number : numbers) {


            if (number != 0) {

                numbers[index++] = number;

            }

        }


        while (index < numbers.length) {

            numbers[index++] = 0;

        }

    }


    public static void main(String[] args) {


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


        moveZeros(numbers);


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

    }

}

Output

[1,3,12,0,0]

Step-by-Step Explanation

Input:

[0,1,0,3,12]

Initial:

index = 0

Read:

0

Skip.


Read:

1

Place:

numbers[0] = 1

Array:

[1,1,0,3,12]

Read:

3

Place:

numbers[1] = 3

Array:

[1,3,0,3,12]

Read:

12

Place:

numbers[2] = 12

Array:

[1,3,12,3,12]

Fill remaining:

[1,3,12,0,0]

Complexity Analysis

Time:

O(n)

Space:

O(1)

Advantages

  • Fewer write operations than swap approach.
  • Maintains order.
  • In-place solution.
  • Production friendly.

Drawbacks

  • Slightly less intuitive.
  • Requires overwriting logic.

Approach 4 — Using Java Streams

Java Streams provide a functional programming approach.

The idea:

  1. Filter non-zero elements.
  2. Add zeros at the end.

Java Program

import java.util.Arrays;
import java.util.stream.IntStream;

public class MoveZerosStreams {


    public static int[] moveZeros(
            int[] numbers) {


        long zeroCount =
                Arrays.stream(numbers)
                        .filter(n -> n == 0)
                        .count();


        int[] result =
                IntStream.concat(

                    Arrays.stream(numbers)
                            .filter(n -> n != 0),

                    IntStream.generate(() -> 0)
                            .limit(zeroCount)

                )
                .toArray();


        return result;

    }


    public static void main(String[] args) {


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


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

    }

}

Output

[1,3,12,0,0]

Step-by-Step Explanation

Original:

[0,1,0,3,12]

Filter non-zero:

[1,3,12]

Count zeros:

2

Generate:

[0,0]

Combine:

[1,3,12,0,0]

Complexity Analysis

Time:

O(n)

Space:

O(n)

Advantages

  • Clean functional style.
  • Easy to understand.
  • Useful in stream-based processing.

Drawbacks

  • Creates a new array.
  • Not in-place.
  • More memory usage.

Approach 5 — Partition Approach

Moving zeros to the end is similar to partitioning an array.

The idea is:

Separate:

Non-zero values

and

Zero values

Partition Concept

Example:

Input:

[0,5,0,2,8]

Partition:

Left side:

[5,2,8]

Right side:

[0,0]

Result:

[5,2,8,0,0]

Java Program

import java.util.Arrays;

public class MoveZerosPartition {


    public static void moveZeros(
            int[] numbers) {


        int left = 0;


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


            if (numbers[right] != 0) {


                int temp =
                        numbers[left];


                numbers[left] =
                        numbers[right];


                numbers[right] =
                        temp;


                left++;

            }

        }

    }


    public static void main(String[] args) {


        int[] numbers =
                {0,5,0,2,8};


        moveZeros(numbers);


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

    }

}

Output

[5,2,8,0,0]

In-Place vs Extra Space

Approach In-Place Space
Extra Array ❌ O(n)
Two Pointer Swap ✅ O(1)
Optimized Two Pointer ✅ O(1)
Streams ❌ O(n)
Partition ✅ O(1)

Primitive vs Object Arrays

Primitive Array

Example:

int[]

Advantages:

  • Faster performance.
  • Less memory.
  • No boxing overhead.

Recommended for:

Large numeric arrays

Object Array

Example:

Integer[]

Advantages:

  • Works with Collections.
  • Supports generics.

Example:

List<Integer>

Comparison of All Approaches

Approach Time Space Stable Recommended
Extra Array O(n) O(n) Yes Learning
Two Pointer Swap O(n) O(1) Yes Interview
Optimized Two Pointer O(n) O(1) Yes Production
Streams O(n) O(n) Yes Functional Style
Partition O(n) O(1) Yes Low Memory

Common Interview Mistakes

Mistake 1

Using nested loops.

Example:

for every zero

shift all elements

Complexity:

O(n²)

Avoid.


Mistake 2

Changing order of elements.

Wrong:

[0,1,0,3,12]

↓

[12,1,3,0,0]

Correct:

[1,3,12,0,0]

Mistake 3

Creating unnecessary arrays.

If interviewer asks:

Solve in-place

Do not use:

new int[n]

Mistake 4

Not handling all-zero arrays.

Example:

[0,0,0]

Output:

[0,0,0]

Mistake 5

Ignoring negative numbers.

Example:

Input:

[0,-1,2,0,-5]

Output:

[-1,2,-5,0,0]

Edge Cases

Input Output
[] []
[0] [0]
[1,2,3] Same array
[0,0,1] [1,0,0]
[-1,0,2] [-1,2,0]

Interview Follow-up Questions

Q1. Move zeros to beginning.

Q2. Move negative numbers to one side.

Q3. Remove duplicates from sorted array.

Q4. Partition array around pivot.

Q5. Move all even numbers first.

Q6. Solve without changing order.

Q7. Solve with minimum swaps.

Q8. What is the optimal approach?


Related Problems

  • Remove Duplicates from Array
  • Partition Array
  • Sort Colors
  • Move Negative Numbers
  • Remove Element
  • Two Pointer Problems
  • Array Rotation

Key Takeaways

  • Moving zeros is a classic two pointer problem.
  • The best interview solution is:
Two Pointer

Complexity:

Time: O(n)

Space: O(1)
  • Maintain relative order of non-zero elements.
  • Avoid unnecessary shifting operations.
  • Choose approach based on:
    • Memory constraints
    • Readability
    • Performance requirements

Frequently Asked Interview Questions

Q1. What is the optimal solution?

Optimized two pointer approach.

Time: O(n)

Space: O(1)

Q2. Why use two pointers?

Because we can rearrange elements in one pass without extra memory.


Q3. Is order preserved?

Yes.

The relative order of non-zero elements remains unchanged.


Q4. Can this be done without modifying the array?

Yes.

Use:

  • Extra array
  • Streams

Q5. Production recommendation?

For most applications:

In-place two pointer approach

because it provides:

  • Best memory usage
  • Linear performance
  • Simple implementation

Interview Tip

When asked:

"Move all zeros to the end of an array."

Clarify:

  1. Should order be preserved?
  2. Can the array be modified?
  3. Is extra memory allowed?

Then explain:

  1. Brute Force
  2. Extra Array
  3. Two Pointer Swap
  4. Optimized Two Pointer
  5. Stream Approach

The ability to explain why O(n) time and O(1) space is optimal demonstrates strong understanding of Java arrays, memory management, and algorithm design.