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

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

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

Learn the Move Zeroes problem in DSA with a beginner friendly guide. We compare brute force, an extra array, and the two pointer trick, with dry runs for all three and ten interview questions at the end. As a developer I will be using Java code but pseudo-codes, explanation and dry runs are language neutral and you can understand the concept easily. So don’t skip it because language is just a syntax.

1. Introduction

The Move Zeroes problem in DSA is a small question with a big lesson hiding inside. You have probably seen it on a practice site and thought it looked easy. The catch shows up the moment somebody asks you to do it without a second array.

Here is the task in plain words. Somebody hands you an array of numbers, and some of them are zeroes. Push every zero to the end, keep the other numbers in their original order, and change the array in place.

Those last three words carry all the weight. Drop them and this is a five-minute exercise. Keep them and it becomes a genuine test of how you think about memory.

In the last article we used Kadane’s Algorithm to sweep an array once while tracking a running best. Now we sweep again, except this time we move values rather than sums. Brute force comes first, an extra array comes second, and the two pointer version lands last.

1.1 What This Article Covers

Here is the road map for the rest of the guide.

  • A plain statement of the problem, plus the two words most people skim past.
  • Three small ideas, in-place editing, a slow writer, and a fast reader.
  • Three approaches, each with pseudocode, code, a dry run, and its real cost.
  • A side-by-side table, and a short guide on which one to reach for.
  • Two follow-up questions interviewers like to bolt on afterwards.
  • The mistakes that cost people offers, and a small program that ties it together.
  • Ten interview questions with short, quotable answers.

2. Understanding the Problem

Let us pin down the rules first. Clear rules save you from silly bugs later, and reading them aloud costs about thirty seconds.

2.1 The Rules in Plain Words

Every version of this question comes down to the same four rules.

  • You receive 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.
  • Editing happens in place, so the method returns nothing at all.

Worth knowing about the original version of this question: the array holds up to about 10,000 numbers, and any integer value is fair game, positive or negative. Only a value of exactly zero counts as a zero, which matters more than it sounds.

2.2 A First Example

Take [0, 1, 0, 3, 12]. The answer is [1, 3, 12, 0, 0].

Look at the surviving order. The 1 still comes before the 3, and the 3 still comes before the 12. Nothing jumped the queue.

That ordering rule is the entire difficulty. Without it you could swap each zero with the last element and finish in seconds. With it, every move you make has to respect the sequence that was already there.

2.3 Why In Place Changes Everything

In place means the caller keeps the same array object, and you rewrite what lives inside it. Build a fresh array and hand it back, and you solved a different problem.

Why do interviewers care so much? Because allocating a second array of the same size doubles your memory. On an array of ten items nobody notices. On an array of ten million, that doubling is the difference between a service that runs and a service that falls over.

So the real question hiding in this puzzle is simple. Can you rearrange data using only a couple of extra variables? Everything below builds towards yes.

💡 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

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

3.1 In-Place Editing

In-place editing means working inside the array you already hold. No second array of the same size ever gets allocated, so your extra memory stays constant however large the input grows.

Think of rearranging books on a shelf. You could carry them all to a second shelf in the right order, or you could slide them along the shelf they are already on. The second way needs no new shelf.

Writing over an old slot is the whole technique. That feels dangerous at first, because you seem to be destroying data. The next two ideas explain why it stays safe.

3.2 A Slow Writer and a Fast Reader

Two indexes walk the same array with different jobs. One reads every value from front to back and never stops. The other marks the slot where the next non-zero value belongs.

  • Every position gets visited exactly once by the reader, zero or not.
  • The writer only advances after it actually stores something.
  • Zeroes make the reader move while the writer stands still.

Picture a queue at a ticket desk where some people leave without buying. The reader is the person calling names, and the writer is the seat counter. Empty-handed leavers do not fill a seat, so the counter waits.

3.3 Why the Writer Never Overtakes the Reader

Here is the guarantee that makes overwriting safe. The writer starts at the same place as the reader, and it advances at most once per reading step.

So the writer either sits level with the reader or trails behind it. Never ahead. Every slot the writer touches has already been read, which means no value gets destroyed before we used it.

Trace the two cases and you can see it. On a non-zero value both indexes move one step, so the gap stays the same. On a zero only the reader moves, so the gap widens by one. Nothing ever narrows it.

That gap has a meaning too. It is exactly the number of zeroes seen so far, which tells you how many slots the tail will need at the end.

4. Approach 1: Brute Force with Shifting

The first idea most beginners reach for feels natural. Find a zero, 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 tracks how many zeroes already sit at the back, and the loop stops before them. Skip that guard and you would shift the same zeroes forever. Notice too that the read position stays put after a shift, because a brand new value just landed there.

4.2 Java Code

import java.util.Arrays;

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(Arrays.toString(nums)); // Output: [1, 3, 12, 0, 0]
    }
}

4.3 Why This Works, Step by Step

Let us walk the logic slowly. Every part has one clear job.

  • The read position scans the array from left to right.
  • Landing on a zero triggers the inner loop, which drags every later value one slot left.
  • That shift leaves a free slot at the very end, so a zero goes there.
  • Bumping the count records that one more zero now sits safely at the back.
  • Any other value means we simply step the read position forward.

This solution edits the array in place, so it does respect the main rule. Sadly it repeats an enormous amount of work, which the next two approaches fix.

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.

  • The read index is the position the outer loop is looking at right now.
  • Value there is simply the number sitting at that position.
  • Zeroes parked counts how many zeroes already sit safely at the back.

Watch two things as you read. The read index only moves forward when no shift happened. The parked count grows by one every time we send a zero to the back.

Step Read index Value there Action Array after Zeroes parked
1 0 0 Shift left, park a zero at the end [1, 0, 3, 12, 0] 1
2 0 1 Not zero, so move forward [1, 0, 3, 12, 0] 1
3 1 0 Shift left, park a zero at the end [1, 3, 12, 0, 0] 2
4 1 3 Not zero, so move forward [1, 3, 12, 0, 0] 2
5 2 12 Not zero, so move forward [1, 3, 12, 0, 0] 2

Look at step one and step two together. After the shift, the read index 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 the length is 5 and two zeroes are parked, so the guard allows positions below 3. Since the read index has climbed to 3, the loop ends. We never look at the last two slots 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 everything behind it. With many zeroes that becomes n shifts of n elements, so the time lands at O(n squared).

Space stays at O(1), since a couple of counters cover everything. The memory rule is satisfied, and only the speed lets us down.

Picture the worst input: an array that starts with thousands of zeroes in a row. Every one of them drags the entire tail one step left. For a tiny array nobody notices, and 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, packed from the left. Whatever space is left over becomes the zeroes. Finally copy the result back.

5.1 Pseudocode

temp = new array of size n     // many languages zero-fill this for you
k = 0
for each num in nums:
    if num != 0:
        temp[k] = num
        k = k + 1
copy temp back into nums

One line deserves a note. Plenty of languages hand you a fresh integer array already filled with zeroes, which is a free head start. Should yours leave that memory undefined, write the tail zeroes yourself before copying back.

5.2 Java Code

import java.util.Arrays;

public class MoveZeroesExtraArray {
    public static void moveZeroes(int[] nums) {
        int[] temp = new int[nums.length];   // Java fills this with zeroes
        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(Arrays.toString(nums)); // Output: [1, 3, 12, 0, 0]
    }
}

5.3 Reading the Code

  • First we build a scratch array of the same length, pre-filled with zeroes.
  • Then we walk the input and copy only the non-zero values across, packed from the left.
  • Because they get copied in order, the relative order survives untouched.
  • The tail of the scratch array is still zeroes, so the zeroes land at the back for free.
  • Last, we copy everything back into the original array, which keeps the caller’s reference valid.

That final copy-back is not optional. Skip it and you have merely built a correct answer in a place nobody can see, while the caller’s array sits unchanged.

5.4 Dry Run of the Extra Array

This trace is the easiest of the three. We read the input from left to right and only care about non-zero values. Remember that the scratch array arrives already full of zeroes.

Step Value read Zero? Action Scratch array after Next free slot
1 0 Yes Skip it, write nothing [0, 0, 0, 0, 0] 0
2 1 No Copy 1 into slot 0 [1, 0, 0, 0, 0] 1
3 0 Yes Skip it, write nothing [1, 0, 0, 0, 0] 1
4 3 No Copy 3 into slot 1 [1, 3, 0, 0, 0] 2
5 12 No Copy 12 into slot 2 [1, 3, 12, 0, 0] 3

Notice that we never wrote a single zero ourselves. The zeroes in the last two slots were already sitting there when the array came into existence. That free head start is what makes this version so short.

The final copy-back leaves the caller looking at [1, 3, 12, 0, 0]. Compare this trace with the brute force one. Same answer, five steps instead of five plus two full shifts, and we paid for a whole second array to get it.

5.5 Time and Space Cost

Time drops to O(n), which is a real win. One pass fills the scratch array and one pass copies it back, so two passes total.

Space climbs to O(n), and avoiding exactly that was the point of the problem. An interviewer will push back here almost every time, so get in first and name the cost yourself.

💡 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 for 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 the insert slot and push that slot forward. When the walk ends, everything from the insert slot onward becomes 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

import java.util.Arrays;

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(Arrays.toString(nums)); // Output: [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.

  • The insert slot starts at 0, because the first non-zero value belongs at the very front.
  • Our first loop reads every number once, and no inner loop appears anywhere, which is the whole point.
  • Any non-zero value gets written at the insert slot, and that slot then steps ahead by one.
  • Zeroes are skipped silently. We never write them, so they simply fall behind.
  • After the loop, the insert slot equals the count of non-zero values, so everything from there on must become a zero.
  • Our second loop fills that tail with zeroes and finishes the job.

Here is the part that trips people up. Does writing at the insert slot destroy a value we still need? It cannot, for the reason section 3.3 laid out. The writer never runs ahead of the reader, so every slot it touches 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.

6.4 Time and Space Cost

Each slot gets read once and written at most once, so the time cost is O(n). Two passes happen, yet both are straight-line walks with no nesting.

Space never grows. A single index variable covers any input length, which puts us at O(1) and satisfies the in-place rule.

So this approach matches the extra-array version on speed and matches the brute force on memory. Getting the best of both is exactly why interviewers wait for 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 the insert slot crawls forward while the reader races ahead.

Step Value read Zero? Action Array after Insert slot
1 0 Yes Skip it, write nothing [0, 1, 0, 3, 12] 0
2 1 No Write 1 at slot 0 [1, 1, 0, 3, 12] 1
3 0 Yes Skip it, write nothing [1, 1, 0, 3, 12] 1
4 3 No Write 3 at slot 1 [1, 3, 0, 3, 12] 2
5 12 No Write 12 at slot 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 last two values are leftover junk, and the reader has already passed them. Since the insert slot is 3, the second loop overwrites both with zeroes.

Fill step Slot Action Array after
1 3 Write a zero [1, 3, 12, 0, 12]
2 4 Write 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 problem in DSA two pointer dry run

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.

7.2 Two Quick Edge Cases

Two inputs sit at the extremes, and both fall out of the same code with no special handling.

Input Insert slot after pass one What pass two does Result
[0, 0, 0] 0 Writes a zero over all three slots [0, 0, 0]
[4, 5, 6] 3 Nothing, the tail is empty [4, 5, 6]

An all-zero array never advances the insert slot, so pass two rewrites every position with the zero it already held. Wasteful, harmless, and correct.

An array with no zeroes writes each value back onto itself, and pass two has nothing left to do. Again wasteful, again harmless. Section 9.1 shows how to skip that waste entirely.

8. Comparing the Three Approaches

All three approaches give the right answer. They simply charge different prices for it.

Point Brute Force Extra Array Two Pointer
Time O(n squared) O(n) O(n)
Extra space O(1) O(n) O(1)
Edits in place Yes No, needs a copy-back Yes
Passes over the array Many Two Two
Keeps the original order Yes Yes Yes
Work at 10,000 values Up to 100 million steps 20,000 steps 20,000 steps
Good for interviews As a starting point As the middle step As the final answer

Read the space row against the time row. Brute force is cheap on memory and expensive on time. The extra array flips that exactly. Only the two pointer version refuses to pay either price.

8.1 Which One Should You Pick?

In real code the answer is never in doubt, and here is the short guide.

  • Reach for the two pointer version by default. It is fast, in place, and short.
  • Use the extra array only when the original must stay untouched for somebody else.
  • Keep brute force as a whiteboard opener, never as shipped code.
  • Switch to the swap variant in section 9.1 when writes are genuinely expensive.

In an interview, walk that 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. Two Common Follow-Ups

Solve the base problem quickly and a follow-up usually arrives. These two show up most often, and both reuse the writer-and-reader idea you already have.

9.1 Minimise the Number of Writes

The original problem statement adds a bonus question: can you cut the total number of operations? Our version always performs one write per slot, even when the array holds no zeroes at all.

Swapping fixes that. Instead of overwriting, exchange the current value with whatever sits at the insert slot. Add a guard so a value never swaps with itself, and untouched arrays cost nothing.

import java.util.Arrays;

public class MoveZeroesSwap {
    public static void moveZeroes(int[] nums) {
        int insert = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                if (i != insert) {              // skip pointless self-swaps
                    int temp = nums[insert];
                    nums[insert] = nums[i];
                    nums[i] = temp;
                }
                insert++;
            }
        }
    }

    public static void main(String[] args) {
        int[] nums = { 0, 1, 0, 3, 12 };
        moveZeroes(nums);
        System.out.println(Arrays.toString(nums)); // Output: [1, 3, 12, 0, 0]
    }
}

Three things changed, and each one matters.

  • The second loop vanished, because swapping carries the zeroes to the tail as a side effect.
  • Every exchange moves a zero backwards and a real value forwards at the same time.
  • The guard skips a swap when both indexes point at the same slot, which is the common case early on.

Cost stays at O(n) time and O(1) space, so the Big-O never changes. What changes is the constant. An array with no zeroes now performs zero writes instead of n, and that is exactly what the bonus question was asking for.

9.2 Push the Zeroes to the Front Instead

A neat variation flips the target. Send every zero to the front, and keep the non-zero values in their original order behind them. So [0, 1, 0, 3, 12] should become [0, 0, 1, 3, 12].

Resist the urge to invent a new technique. Just run the same algorithm backwards: start both indexes at the last slot and walk towards the front.

import java.util.Arrays;

public class ZeroesToFront {
    public static void zeroesToFront(int[] nums) {
        int insert = nums.length - 1;
        for (int i = nums.length - 1; i >= 0; i--) {
            if (nums[i] != 0) {
                nums[insert] = nums[i];
                insert--;
            }
        }
        while (insert >= 0) {
            nums[insert] = 0;
            insert--;
        }
    }

    public static void main(String[] args) {
        int[] nums = { 0, 1, 0, 3, 12 };
        zeroesToFront(nums);
        System.out.println(Arrays.toString(nums)); // Output: [0, 0, 1, 3, 12]
    }
}

Everything mirrors the forward version. The writer still trails the reader, except both now travel right to left, so the same safety guarantee holds.

Walking backwards to preserve order is a pattern worth remembering. Merge Sorted Array leans on the same trick, and once you have seen it twice it stops feeling clever and starts feeling obvious.

10. Common Mistakes and Pitfalls

A handful of small traps catch beginners on this problem. Read them once and you will dodge most of them.

  • Building a new array and returning it. That solves a different problem, because the caller keeps looking at the untouched original.
  • Forgetting the second loop. Without it you leave junk in the tail, like that stray [1, 3, 12, 3, 12].
  • Sorting the array to push zeroes back. Sorting reorders the other numbers too, which breaks the main rule.
  • Advancing the read position after a shift in the brute force version. A fresh value just landed there and still needs inspecting.
  • Advancing the insert slot on a zero. The writer must stand still, or the zeroes get baked into the front.
  • Skipping the copy-back in the extra array version. The correct answer then lives somewhere nobody can see it.
  • Treating negative numbers as blanks. Only a value of exactly zero counts, and -3 is an ordinary value.

Empty and single-element arrays need no special handling either. Every approach above walks them harmlessly and leaves them exactly as they were.

11. Practical Walkthrough: A Reading Compactor

Let us tie everything into one small program. Sensor logs often use 0 to mean “no reading”. This program compacts the real readings to the front and reports what it did.

11.1 The Program

import java.util.Arrays;

public class ReadingCompactor {

    public static void report(int[] readings) {
        if (readings == null || readings.length == 0) {
            System.out.println("No readings to process.");
            return;
        }

        int[] before = Arrays.copyOf(readings, readings.length);

        int insert = 0;
        for (int value : readings) {
            if (value != 0) {
                readings[insert] = value;
                insert++;
            }
        }
        int kept = insert;
        while (insert < readings.length) {
            readings[insert] = 0;
            insert++;
        }

        System.out.println(Arrays.toString(before) + " -> " + Arrays.toString(readings)
                + "  (" + kept + " kept, " + (readings.length - kept) + " blanked)");
    }

    public static void main(String[] args) {
        report(new int[] { 0, 1, 0, 3, 12 });
        report(new int[] { 0, 0, 0 });
        report(new int[] { 4, 5, 6 });
    }
}
[0, 1, 0, 3, 12] -> [1, 3, 12, 0, 0]  (3 kept, 2 blanked)
[0, 0, 0] -> [0, 0, 0]  (0 kept, 3 blanked)
[4, 5, 6] -> [4, 5, 6]  (3 kept, 0 blanked)

11.2 What the Output Tells You

Three inputs, three different shapes of answer. That is the point of the exercise.

  • A mixed log compacts the real readings forward and counts what survived.
  • An all-blank log keeps its shape, and the counter honestly reports zero readings kept.
  • A log with no blanks passes through untouched, with nothing left for the fill loop.

Notice the small but useful trick in the middle. The insert slot after pass one is exactly the number of real readings, so we grab it before the fill loop moves it. One variable answers two questions at once.

Notice how little changed from the plain two pointer version too. The scan is identical. We only added a guard at the top, a snapshot for the report, and a friendlier line at the bottom.

12. Interview Questions

Q: What is the Move Zeroes problem in DSA?

A: Somebody hands you an array of integers, and you must push every zero to the end while keeping the non-zero numbers in their original relative order. The array changes in place, so the method returns nothing.

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

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

Q: What does in place actually mean here?

A: It means rewriting the array the caller already holds, using only a couple of extra variables. Allocating a second array of the same size doubles your memory, which is exactly what the problem asks you to avoid.

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 slot never runs ahead of the reading position, 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?

A: Brute force shifting runs in O(n squared) time with O(1) space. The extra array version runs in O(n) time but uses O(n) space. Two pointers give O(n) time with O(1) space, which beats both.

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 performs fewer writes when zeroes are rare. Either is fine in an interview if you can defend the choice.

Q: How do I reduce the total number of write operations?

A: Use the swap variant and guard against swapping a slot with itself. An array holding no zeroes then performs no writes at all, instead of rewriting every position.

Q: How would I move the zeroes to the front instead?

A: Run the same algorithm backwards. Start both indexes at the last slot, walk towards the front, then fill the remaining front slots with zeroes. Order is preserved for the same reason as before.

Q: Which edge cases should I test before I say I am done?

A: Try an array of all zeroes, an array with no zeroes, a single element, zeroes only at the front, and zeroes only at the back. Those five inputs catch nearly every bug here.

13. Conclusion

Let us wrap up what we covered. The Move Zeroes problem in DSA looks like a beginner warm-up, and in a way it is. Yet the two pointer idea inside it is a real skill you will reuse constantly.

We started with brute force, dragging the tail left every time a zero appeared. Correct and in place, but slow at O(n squared), because each zero can shift the entire array.

The extra array came next and pulled the time down to O(n). Copy the non-zero values into a scratch array, let the leftover slots serve as zeroes, then copy back. Fast and simple, at the cost of doubling your memory.

Two pointers finished the job by refusing both prices. Pull the non-zero values forward with a writer that trails the reader, then flood the tail with zeroes. That is O(n) time and O(1) space at the same time.

Along the way we handled the usual follow-ups. Swapping instead of overwriting cuts the write count to nothing on a clean array. Running the same walk backwards sends the zeroes to the front instead.

So take the pattern, not just the answer. Keep a writer that only advances when it stores something, let the reader run ahead, and clean up whatever the writer left behind. Once that habit feels natural, Remove Duplicates, Remove Element, and a shelf of string problems all get easier.

14. Further Reading

Leave a Comment