给定一个包含元素的数组x
,我必须找到四个相加后等于 0 的数字。我还需要确定存在多少这样的总和。
所以三次时间涉及三个嵌套迭代器,所以我们只需要查找最后一个数字(使用二分搜索)。
相反,通过使用笛卡尔积(X 和 Y 的相同数组),我们可以将所有对及其总和存储在辅助数组中。所以对于每个总和d
,我们只需要寻找-d
.
这应该类似于(接近)二次时间:
public static int quad(Double[] S) {
ArrayList<Double> pairs = new ArrayList<>(S.length * S.length);
int count = 0;
for (Double d : S) {
for (Double di : S) {
pairs.add(d + di);
}
}
Collections.sort(pairs);
for (Double d : pairs) {
int index = Collections.binarySearch(pairs, -d);
if (index > 0) count++; // -d was found so increment
}
return count;
}
由于x
是 353(对于我们特定的数组输入),解决方案应该是 528,但我使用这个解决方案只找到 257。对于我们的立方时间,我们能够找到所有 528 个 4 和
public static int count(Double[] a) {
Arrays.sort(a);
int N = a.length;
int count = 0;
for(int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) {
int l = Arrays.binarySearch(a, -(a[i] + a[j] + a[k]));
if (l > 0) count++;
}
}
}
return count;
}
是否有任何机会丢失了double的精度?
编辑:讨论了使用BigDecimal
代替double
,但我们担心它会对性能产生影响。我们只处理数组中的 353 个元素,那么这对我们来说意味着什么吗?
编辑编辑:如果我错误地使用 BigDecimal,我深表歉意。我以前从来没有和图书馆打过交道。因此,经过多次建议后,我尝试使用 BigDecimal
public static int quad(Double[] S) {
ArrayList<BigDecimal> pairs = new ArrayList<>(S.length * S.length);
int count = 0;
for (Double d : S) {
for (Double di : S) {
pairs.add(new BigDecimal(d + di));
}
}
Collections.sort(pairs);
for (BigDecimal d : pairs) {
int index = Collections.binarySearch(pairs, d.negate());
if (index >= 0) count++;
}
return count;
}
因此,它能够找到 261 个解决方案,而不是 257 个。这可能表明存在问题double
,实际上我正在失去精度。但是261距离528很远,但我无法找到原因。
LASTEDIT:所以我相信这是可怕而丑陋的代码,但它似乎仍然有效。我们已经尝试过 while 但使用 BigDecimal 我们现在能够获得所有 528 个匹配项。
我不确定它是否足够接近二次时间,时间会证明一切。
我给你介绍怪物:
public static int quad(Double[] S) {
ArrayList<BigDecimal> pairs = new ArrayList<>(S.length * S.length);
int count = 0;
for (Double d : S) {
for (Double di : S) {
pairs.add(new BigDecimal(d + di));
}
}
Collections.sort(pairs);
for (BigDecimal d : pairs) {
BigDecimal negation = d.negate();
int index = Collections.binarySearch(pairs, negation);
while (index >= 0 && negation.equals(pairs.get(index))) {
index--;
}
index++;
while (index >= 0 && negation.equals(pairs.get(index))) {
count++;
index++;
}
}
return count;
}