我已经解决了这个问题,但我想减少它的运行时间。那么有什么方法可以完成这项任务吗? 任务:给定一个数组nums,写一个函数将所有0都移到它的末尾,同时保持非零元素的相对顺序。
例如,给定nums = [0,1,0,3,12],在调用函数后,nums应为[1,3,12,0,0]。
我的解决方案:
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];
}
}
}
答案 0 :(得分:2)
您可以利用默认情况下将为所有0创建int
的原始数组的事实。因此,您只需要创建一个与原始数组长度相同的结果数组,并将源数组中的非零元素复制到其中:
int[] result = new int[array.length];
int k = 0;
for (int v : array) {
if (v != 0) {
result[k++] = v;
}
}
我已经实现了你的解决方案的JMH基准测试,这个基于一个阵列初始化,在-10和10之间有1亿个随机整数。结果是( 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
表明这个解决方案确实有点快(208 ms vs 251 ms)。
完整性的基准代码:
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;
}
}
答案 1 :(得分:1)
试试这个:
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;
}
}
}
我首先创建了一个不包含'0'的所有索引的“掩码”(一旦O(N)重新遍历数组)。然后你只需创建新的数组(O(N)后遍历所有数组)。因此复杂性将是O(N)。