UCF HSPT 2016 - Chomp Chomp

时间:2016-03-10 15:00:15

标签: java algorithm performance

我在UCF HSPT编程竞赛中找到问题#9的有效解决方案时遇到了很多麻烦。整个pdf我们可以查看here,问题被称为" Chomp Chomp!"。

基本上问题涉及到2" chmps"在阵列中,每个chomp是来自阵列的连续元素链,并且2个chomp必须至少具有它们之间的元素,这些元素不会被扼杀。"一旦两个" chomp"确定,两个" chomps"中所有元素的总和。必须是输入中给出的数字的倍数。我的解决方案基本上是一种蛮力,贯穿每一个可能的" chomp"我试图通过存储先前计算的chomps总和来提高它的速度。

我的代码:

import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;

public class chomp {
    static long[] arr;

    public static long sum(int start, int end) {
        long ret = 0;
        for(int i = start; i < end; i++) {
            ret+=arr[i];
        }
        return ret;
    }

    public static int sumArray(int[] arr) {
        int sum = 0;
        for(int i = 0; i < arr.length; i++) {
            sum+=arr[i];
        }
        return sum;
    }

    public static long numChomps(long[] arr, long divide) {
        HashMap<String, Long> map = new HashMap<>();
        int k = 1;
        long numchomps = 0;
        while(true) {
            if (k > arr.length-2) break;
            for (int i = 0; i < arr.length -2; i++) {
                if ((i+k)>arr.length-2) break;
                String one = i + "";
                String two = (i+k) + "";
                String key1 = one + " " + two;
                long first = 0;
                if(map.containsKey(key1)) {
                    //System.out.println("Key 1 found!");
                    first = map.get(key1).longValue();
                } else {
                    first = sum(i, i+k);
                    map.put(key1, new Long(first));
                }
                int kk = 1;
                while(true){
                    if (kk > arr.length-2) break;
                    for (int j = i+k+1; j < arr.length; j++) {
                        if((j+kk) > arr.length) break;
                        String o = j + "";
                        String t = (j+kk) + "";
                        String key2 = o + " " + t;
                        long last = 0;
                        if(map.containsKey(key2)) {
                            //System.out.println("Key 2 found!");
                            last = map.get(key2).longValue();
                        } else {
                            last = sum(j, j+kk);
                            map.put(key2, new Long(last));
                        }
                        if (((first+last) % divide) == 0) {
                            numchomps++;
                        }
                    }
                    kk++;
                }
            }
            k++;
        }
        return numchomps;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in);
        int n = Integer.parseInt(in.nextLine());
        for(int i = 1; i <= n; i++) {
            int length = in.nextInt();
            long divide = in.nextLong();
            in.nextLine();
            arr = new long[length];
            for(int j = 0; j < length; j++) {
                arr[j] = (in.nextLong());
            }
            //System.out.println(arr);
            in.nextLine();
            long blah = numChomps(arr, divide);
            System.out.println("Plate #"+i + ": " + blah);
        }

    }

}

我的代码得到了正确答案,但似乎花了太长时间,特别是对于大型输入,当数组的大小为1000或更大时。我试图提高我的算法的速度,我存储以HashMap计算的先前总和,但这并没有大大提高我的程序的速度。我该怎么做才能提高速度,以便在10秒内运行?

1 个答案:

答案 0 :(得分:0)

效率低下的第一个原因是不断重新计算总和。你应该制作一个部分和long [n] partial;的辅助数组,然后你可以简单地sum(i, i + k)来调用partial[i + k] - partial[i]

现在问题减少到寻找索引i<j<k<m

    (partial[j] - partial[i] + partial[m] - partial[k]) % divide == 0

或重新安排条款,

    (partial[j] + partial[m]) % divide == (partial[i] + partial[k]) % divide 

要查找它们,您可以考虑一系列三元组(s, i, j)其中s = (partial[j] - partial[i]) % divide,按s稳定排序,并检查非重叠&#34; chomps&#34的相等范围;

这种方法改善了从O(n 4 )到O(n 2 log n)的性能。现在你可以将它改进为O(n log n)。