我想找到-n至n范围内的四个数字的所有组合,这些数字加起来为零。有没有有效的算法来解决这个问题?
#include <iostream>
using namespace std;
int main()
{
int i, j, k, l;
int size = 20;
for (i = -size; i <= size; i++)
{
for (j = -size; j <= size; j++)
{
for (k = -size; k <= size; k++)
{
for (l = -size; l <= size; l++)
{
if (i + j + k + l == 0)
{
cout << i << " " << j << " " << " " << k << " " << l << endl;
}
}
}
}
}
return 0;
}
答案 0 :(得分:1)
可能有很多方法可以优化此算法,但是这里有一些简单的方法。
首先,您完全不需要遍历数字的最终循环:
for (l = -size; l <= size; l++)
...
这是因为现在已经定义了前三个数字,因此只有一个可能的数字可以使所有4个数字的总和为零。您要做的就是找出该数字是多少,并检查它是否在-n到+ n范围内。
int l = 0 - (i+j+k);
if (-l >= -size && l <= size)
....
第二,在许多情况下,可以缩短第三个循环,例如,如果i和j均为-size,则可能导致所有四个数字加到零的k的唯一可能值为+ size。使用这个想法,我们可以在此循环上附加界限,在很多情况下可以缩短循环时间。
这两个优化将大大提高该算法的速度。
答案 1 :(得分:0)
请参阅我的代码和注释。 算法效率为O(N ^ 3),求解总数也为O(N ^ 3)。
#include <cstdio>
#include <algorithm>
int main(){
int size = 20;
for(int a = -size; a <= size; ++a){
for(int b = -size; b <= size; ++b ) {
int c_min, c_max, d, c;
//1. a + b + c +d = 0.
//2. d = -(a+b+c)
//3. -size <= d <= size
//4. -size <= -(a+b+c) <= size
//5. size >= a +b + c >= -size
//6. -size - (a+b) <= c <= size - (a+b)
//7. but, -size <= c <= size.
c_min = std::max(-size, -size - (a+b) ) ;
c_max = std::min(size, size - (a+b) ) ;
for(c = c_min ; c <= c_max; ++c){
d = -(a+b+c);
printf("a = %d b = %d c = %d d= %d\n", a,b,c,d);
}
}
}
return 0;
}