我有一个嵌套循环来查找4和4组中1和x之间所有可能的数字组合,其中a< b< c< d。
调用方法,因为发现每个组对这些数字的总和进行简单的等效性测试。
循环确实起作用并产生预期的输出(这个特定的x的1组数字),然而找到这个答案需要12秒以上,而另外〜5来测试剩余的可能性,这绝对是不好的,考虑到x值是< 1000。
我尝试让外循环迭代a&lt; x - 3次,b循环b <1。 x - 2次,低至d <1。 x次没有显着差异。
更改此循环有什么更好的方法?
for (a = 1; a < x; a++) {
for (b = a + 1; b < x; b++) {
for (c = b + 1; c < x; c++) {
for (d = c + 1; d < x; d++) {
check(a, b, c, d);
}
}
}
}
答案 0 :(得分:2)
如此深层次的嵌套,你可以引入的任何早期退出 - 特别是在外环 - 可以获得巨大收益。
例如,您写道check
正在测试a + b + c + d == x && a * b * c * d == x
- 这样您就可以计算中间和和产品,并在遇到数字时中断,这样可以选择以后的数字。
一个例子:
for (a = 1; a < x; a++) {
for (b = a + 1; b < x; b++) {
int sumAB = a + b;
if (sumAB + sumAB > x) break;
int prodAB = a * b;
if (prodAB * prodAB > x) break;
for (c = b + 1; c < x; c++) {
int sumABC = sumAB + c;
if (sumABC + c > x) break;
int prodABC = prodAB * c;
if (prodABC * c > x) break;
for (d = c + 1; d < x; d++) {
int sumABCD = sumABC + d;
if (sumABCD > x) break;
if (sumABCD != x) continue;
int prodABCD = prodABC * d;
if (prodABCD > x) break;
if (prodABCD != x) continue;
printf("%d, %d, %d, %d\n", a, b, c, d);
}
}
}
}
这只是一个示例 - 您可以进一步约束所有检查(例如,将第一次检查设为sumAB + sumAB + 3 > x
)。关键是要关注早期退出。
我为每个循环添加了一个计数器,计算它输入的次数,并尝试了你的版本和我的版本,x = 100.我的版本的循环条目少了几个数量级:
没有提前退出:99,4851,156849,3764376
早期退出:99,4851,1122,848