我在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秒内运行?
答案 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)。