如何加速这段java代码?

时间:2013-05-05 12:19:44

标签: java algorithm

此方法返回正整数数组中的数字(如果它发生的次数超过数组大小的一半),否则返回-1。我需要改进大型数组(10^5<size<10^8)的运行时间。有什么建议?

public static int findResult(int arr[],int len){

    int val=0;
    HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
    for(int i=0;i<len;i++){
        if(map.containsKey(arr[i])){
            val = (Integer)map.get(arr[i]);
            map.put(arr[i], val+1);
        }else{
            val=1; 
            map.put(arr[i], val);
        }
    }
    Iterator<Integer> it=map.keySet().iterator();
    while(it.hasNext()){
        int next=it.next();
        if((Integer)map.get(next)>(len/2)){
            return next;
        }
    }
    return -1;
}

4 个答案:

答案 0 :(得分:6)

您可以在没有地图的情况下执行此操作,无需装箱/取消装箱:

public static int findResult(int[] arr, int len) {
    if(len == 0) return -1;
    if(len == 1) return arr[0];

    int element = arr[0];
    int count = 1;
    for(int i = 1; i < len; i++) {
        if(arr[i] == element) {
            count++;
        } else if(count > 0) {
            count--;
        } else {
            element = arr[i];
            count = 1;
        }
    }

    count = 0;
    for(int a:arr) {
        if(a == element) {
            count++;
        }
    }

    return (count > len / 2) ? element : -1;
}

答案 1 :(得分:1)

为什么不在hashmap中每次输入迭代后与长度(运行的第二个迭代器循环)进行比较?这是在hashmap完成时,您知道结果,而您只需要执行一次。

答案 2 :(得分:0)

此IMO更短,更高效

public static int findResult(int arr[], int len) {
    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
    for (int i = 0; i < len; i++) {
        Integer val = map.get(arr[i]);
        if (val != null) {
            map.put(arr[i], val + 1);
        } else {
            map.put(arr[i], 1);
        }
    }
    for (Entry<Integer, Integer> e : map.entrySet()) {
        if (e.getKey() > (len / 2)) {
            return e.getValue();
        }
    }
    return -1;
}

1)原始版本在地图上使用2个方法调用

if(map.containsKey(arr[i])){
        val = (Integer)map.get(arr[i]);

我使用一个map.get

2)这个

 while(it.hasNext()){
        int next=it.next();
        if((Integer)map.get(next)>(len/2)){

性能非常糟糕,甚至Sonar或FindBugs都会发现它并且建议用我提供的东西替换它

答案 3 :(得分:0)

你可以使用temp变量来存储最大的金额, 每次增加某个变量的计数器时,检查它是否大于你的温度,如果是,则替换它,否则继续,这样你可以在没有第二个循环的情况下完成它而你只知道你的答案是在temp变量中