我有一个问题需要解决。 N
给出了自然数。我需要找到一个自然数列表,它总结到给定的数字,同时反转最多为1。
a + b + c + ... = N
1/a + 1/b + 1/c + ... = 1
a
,b
,c
不一定是唯一的。
我在Java中提出了以下代码。它适用于简单的情况,但N > 1000
已经非常缓慢。
如何重写方法,以便即使对数百万人来说也能快速工作?也许,我应该放弃递归或者用数学技巧切断一些分支,我想念它?
SSCEE:
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;
}
答案 0 :(得分:11)
论文"A Theorem on Partitions", 1963 by Graham, R. L.表明,对于N&gt; 77有一个解决方案,其中使用的数字是dinstinct并提出一个算法来找到这样的分解。
算法如下:
d1, d2, d3, d4, ..., dk
找到分解(N-179)/2
,然后3, 7, 78, 91, 2*d1, 2*d2, 2*d3, ..., 2*dk
是N的分解d1, d2, d3, d4, ..., dk
找到分解(N-2)/2
,然后2, 2*d1, 2*d2, 2*d3, ..., 2*dk
是N的分解但是由于你不关心在分解中有不同的数字,你可以将预计算结果的表的大小减小到60,如果N是奇数,找到{{1}的分解d1, d2, d3, d4, ..., dk
然后(N-9)/2
是N的分解。
答案 1 :(得分:0)
首先,更改第二个条件,这样就不必执行任何浮点算术。改变(1 / a + 1 / b + 1 / c)= 1到bc + ac + ab = abc。您可以使用O(k)分割来计算(提示:先计算右侧)。
其次,巩固你的号码。示例:如果您有a,b,c,a,b作为输入,请合并欺骗并将其存储为两个a,两个b和一个c。
第三,有一种基于DP的解决方案可以有效地解决第一个问题。您还必须存储所有部分答案。但是,您可以非常有效地存储部分答案。例如。存储“x = bc + ac + ab”和“y = abc”作为部分解。将d添加到混合中时,您有xnew = x * d + y,ynew = y * d。
如果您使用这三个指针,您的解决方案可能会更有效。
答案 2 :(得分:-2)
如果数字不必是整数a = b = c = ... = sqrt(N)
是一个解决方案。
如果允许使用负数,则查找a
和b
,以便8a+3b+1=N
(您可以使用Euclide's algorithm计算它们),然后您需要的列表是:
数字3(3a次),数字2(2b次)和数字1(1-a-b次)