【发布时间】:2013-05-11 09:38:25
【问题描述】:
我有一个问题要解决。给定N 自然数。我需要找到一个自然数列表,这些自然数的总和等于给定的数字,同时倒数最大为 1。
a + b + c + ... = N
1/a + 1/b + 1/c + ... = 1
a、b、c 不必是唯一的。
我用 Java 编写了以下代码。它适用于简单的情况,但对于 N > 1000 来说已经非常慢了。
我如何重写该方法,使其即使对数百万也能快速运行?也许,我应该放弃递归或用我错过的数学技巧切断一些分支?
SSCE:
private final static double ONE = 1.00000001;
public List<Integer> search (int number) {
int bound = (int)Math.sqrt(number) + 1;
List<Integer> list = new ArrayList<Integer>(bound);
if (number == 1) {
list.add(1);
return list;
}
for (int i = 2; i <= bound; i++) {
list.clear();
if (simulate(number, i, list, 0.0)) break;
}
return list;
}
//TODO: how to reuse already calculated results?
private boolean search (int number, int n, List<Integer> list, double sum) {
if (sum > ONE) {
return false;
}
//would be larger anyway
double minSum = sum + 1.0 / number;
if (minSum > ONE) {
return false;
}
if (n == 1) {
if (minSum < 0.99999999) {
return false;
}
list.add(number);
return true;
}
boolean success = false;
for (int i = 2; i < number; i++) {
if (number - i > 0) {
double tmpSum = sum + 1.0 / i;
if (tmpSum > ONE) continue;
list.add(i);
success = search(number - i, n - 1, list, tmpSum);
if (!success) {
list.remove(list.size() - 1);
}
if (success) break;
}
}
return success;
}
【问题讨论】:
-
我认为
1/a + 1/b + 1/c + ... = N是一个错字,应该是= 1,不是吗? -
你说逆列表应该总结为 1 (你的公式说 N): a + b + c + ... = N 1 /a + 1/b + 1/c + ... = 1
-
我认为你应该期望运行时 O(n^2) 的量级。如果您实施智能修剪,您可能会节省一个常量工厂,恕我直言,这不会得到回报。我认为你不能用浮点运算来解决这个问题。优化可能应该去 java 编码。
-
为了清楚起见,{a, b, ...} 应该是整数,对吧?另外,你允许正数和负数吗?
-
应该 a, b, c, ... de dinstinct 吗?
标签: java algorithm optimization recursion numbers