如何减少数组的运行时间

时间:2016-01-09 15:14:33

标签: java arrays runtime

我已经解决了这个问题,但我想减少它的运行时间。那么有什么方法可以完成这项任务吗? 任务:给定一个数组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];

            }
    }
}

2 个答案:

答案 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)。