Lesson 19 of 164
Move Zeroes to the End
Given an array of integers, move all the zeros to the end while keeping the relative order of the non-zero elements. Do it in place.
LeetCode: 283. Move Zeroes
Example
Input: [1, 8, 3, 0, 2, 0, 1, 10, 13, 0]
Output: [1, 8, 3, 2, 1, 10, 13, 0, 0, 0]
Input: [0, 3, 5, 9, 0, 0, 23, 2]
Output: [3, 5, 9, 23, 2, 0, 0, 0]Brute force: build a second array
Copy the non-zero elements into a new array. A new int[] starts filled with zeros, so the padding is already there. Then copy it back.
import java.util.Arrays;
public class Main {
static void moveZeroes(int[] nums) {
int[] result = new int[nums.length]; // all zeros
int k = 0;
for (int x : nums) {
if (x != 0) {
result[k++] = x;
}
}
System.arraycopy(result, 0, nums, 0, nums.length);
}
public static void main(String[] args) {
int[] a = {1, 8, 3, 0, 2, 0, 1, 10, 13, 0};
moveZeroes(a);
System.out.println(Arrays.toString(a));
}
}[1, 8, 3, 2, 1, 10, 13, 0, 0, 0]Time: O(n). Space: O(n).
Optimal: in-place write pointer
Keep write, the position where the next non-zero element belongs. Scan the array, and swap each non-zero element into position write. Everything before write is non-zero and in the original order, and everything between write and the scan position is zero.
import java.util.Arrays;
public class Main {
static void moveZeroes(int[] nums) {
int write = 0;
for (int read = 0; read < nums.length; read++) {
if (nums[read] != 0) {
int tmp = nums[write];
nums[write] = nums[read];
nums[read] = tmp;
write++;
}
}
}
public static void main(String[] args) {
int[] a = {1, 8, 3, 0, 2, 0, 1, 10, 13, 0};
moveZeroes(a);
System.out.println(Arrays.toString(a));
int[] b = {0, 3, 5, 9, 0, 0, 23, 2};
moveZeroes(b);
System.out.println(Arrays.toString(b));
}
}[1, 8, 3, 2, 1, 10, 13, 0, 0, 0]
[3, 5, 9, 23, 2, 0, 0, 0]Time: O(n). Space: O(1).
Before the first zero, write == read, and the swap does nothing. Afterwards, nums[write] is always a zero, so each swap moves exactly one zero one step further back.
Edge cases
- No zeros or only zeros: the array does not change.
- An
Integer[]orList<Integer>: sorting withComparator.comparing(x -> x == 0)gives the same result, because the object sort is stable andfalsesorts beforetrue. It takesO(n log n)time. (Arrays.sorton a primitiveint[]takes no comparator.)
