Reputation: 127
I have solved the problem but I want to decrease its runtime. So is there any way to do this task? Task: 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.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
My solution:
public class Solution {
public void moveZeroes(int[] nums) {
int [] nums1=new int[nums.length];
int k=-1;
for(int i=0;i<nums.length;i++){
if(nums[i]!=0){
k++;
nums1[k]=nums[i];
}}
for(int i=0;i<nums1.length;i++){
nums[i]=nums1[i];
}
}
}
Upvotes: 1
Views: 85
Reputation: 1247
try this one:
public class Solution {
public void moveZeroes(int[] nums) {
int [] indexes=new int[nums.length];
int k=0;
for(int i=0;i<nums.length;i++){
if(nums[i]!=0){
indexes[k]==i;
k++;
}
}
for(int i=0;i<nums.length;i++){
if(i<k)
nums[i]=nums[indexes[i]];
else
nums[i]=0;
}
}
}
i have first created a "mask" of all indexes not containing '0'(go over the array once O(N)). then you simply create the new array (go over all the array once O(N)). thus the complexity will be O(N).
Upvotes: 1
Reputation: 137194
You could take advantage of the fact that a primitive array of int
will be created to all 0's by default. As such, you just need to create a result array having the same length of the original array and copy into it the non-zero element from the source array:
int[] result = new int[array.length];
int k = 0;
for (int v : array) {
if (v != 0) {
result[k++] = v;
}
}
I've realized a JMH benchmark of your solution and this one on an array initialized with 100 millions random ints between -10 and 10. The results are (Windows 10, JDK 1.8.0_66, i5-3230M CPU @ 2.60 GHz):
Benchmark Mode Cnt Score Error Units
StreamTest.alternative avgt 30 208,094 ± 29,928 ms/op
StreamTest.shiftSolution avgt 30 250,888 ± 26,086 ms/op
which shows that this solution is indeed a bit faster (208 ms vs 251 ms).
Benchmark code for completeness:
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
@Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.NANOSECONDS)
@Measurement(iterations = 10, time = 1000, timeUnit = TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(3)
@State(Scope.Benchmark)
public class StreamTest {
private static final int[] ARRAY = new Random().ints(100000000, -10, 10).toArray();
@Benchmark
public int[] shiftSolution() {
int[] nums1 = new int[ARRAY.length];
int k = -1;
for (int i = 0; i < ARRAY.length; i++) {
if (ARRAY[i] != 0) {
k++;
nums1[k] = ARRAY[i];
}
}
for (int i = 0; i < nums1.length; i++) {
ARRAY[i] = nums1[i];
}
return nums1;
}
@Benchmark
public int[] alternative() {
int[] result = new int[ARRAY.length];
int k = 0;
for (int v : ARRAY) {
if (v != 0) {
result[k++] = v;
}
}
return result;
}
}
Upvotes: 2