package com.freetymekiyan.algorithms.level.easy;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the
* non-zero elements.
* <p>
* For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
* <p>
* Note:
* You must do this in-place without making a copy of the array.
* Minimize the total number of operations.
* <p>
* Company Tags: Bloomberg, Facebook
* Tags: Array, Two Pointers
* Similar Problems: (E) Remove Elements
*/
public class MoveZeroes {
/**
* Two Pointers. One-pass.
* Track the end of non-zero elements with a pointer.
* Swap non-zero elements to the front.
* For each number n in the array:
* | If n != 0:
* | Swap n nums[cur]
* | cur -> cur+1
* If current number is not zero, swap it to the front.
* Where we track the swap position with another pointer.
*/
public void moveZeroes(int[] nums) {
int cur = 0;
for (int i = 0; i < nums.length; ++i) {
if (nums[i] != 0) {
int temp = nums[cur];
nums[cur++] = nums[i];
nums[i] = temp;
}
}
}
/**
* Two pointers.
* One pointer goes through the array and find positive numbers.
* The other tracks the next position to be filled up.
* Move all positive numbers to the front of the array.
* Then add trailing zeroes after.
*/
public void moveZeroesB(int[] nums) {
if (nums == null || nums.length == 0) {
return;
}
int count = 0;
for (int n : nums) {
if (n != 0) {
nums[count] = n;
count++;
}
}
for (; count < nums.length; count++) {
nums[count] = 0;
}
}
@Test
public void tests() {
MoveZeroes mz = new MoveZeroes();
int[] nums = null;
// null -> null
mz.moveZeroes(nums);
assertNull(nums);
// empty -> empty
nums = new int[]{};
mz.moveZeroes(nums);
assertEquals(nums.length, 0);
assertNotNull(nums);
// [1] -> [1]
nums = new int[]{1};
mz.moveZeroes(nums);
assertArrayEquals(nums, new int[]{1});
// no zero, [1, 2, 3] -> [1, 2, 3]
nums = new int[]{1, 2, 3};
mz.moveZeroes(nums);
assertArrayEquals(nums, new int[]{1, 2, 3});
// all zeroes, [0, 0, 0] -> [0, 0, 0]
nums = new int[]{0, 0, 0};
mz.moveZeroes(nums);
assertArrayEquals(nums, new int[]{0, 0, 0});
// normal case, [0, 1, 0, 3, 12] -> [1, 3, 12, 0, 0]
nums = new int[]{0, 1, 0, 3, 12};
mz.moveZeroes(nums);
assertArrayEquals(nums, new int[]{1, 3, 12, 0, 0});
}
}