Description
The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
Input
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228 ) that belong respectively to A, B, C and D .
Output
For each input file, your program has to write the number quadruplets whose sum is zero.
Sample Input
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
Sample Output
5
大致题意:给你A,B,C,D四个数组,在A,B,C,D中各找一个数,使其和为0,求出种数(另外同一数组中相同数值的看成不同数);
解题思路:这一题大家相信首先想到的是否可以通过枚举得出答案?如果正常枚举的话看一下n的大小,高达4000,时间复杂度为O(n^4);接着我们来看如何降低时间复杂度!首先我们有a+b+c+d=0可得,只要a,b,c确定的话d=-(a+b+c),就是说d随之确定。我们只要查找
-(a+b+c)是否存在于D中即可,可以先对D排序,再二分查找实现。先这样优化一下时间复杂度降为O(n*n*n*log(n));这样时间复杂度还是不行的。还要接着优化。最终我们该把A,B合为一组,C,D合为一组,A,B的组合n*n种,C,D的组合有n*n种,并存储c+d,再排序。当确定a+b的和时(有n*n种)接着从c+d中二分寻找-(a+b)的值即可,另外可能存在多个值等于-(a+b),这时要稍做处理。
AC代码:
# include <cstdio>
# include <algorithm>
using namespace std;
int a[4010], b[4010], c[4010], d[4010];
int c_add_d[16000010];
int main(){
int n, i, j, k, ans, des, left, right, temp, mid, l;
while(scanf("%d", &n)!=EOF){
if(n==0){
printf("0\n");
continue;
}
for(i=1; i<=n; i++){
scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
}
k=1;
for(i=1; i<=n; i++){
for(j=1; j<=n; j++){
c_add_d[k++]=c[i]+d[j];
}
}
sort(c_add_d+1, c_add_d+k);
ans=0;
for(i=1; i<=n; i++){
for(j=1; j<=n; j++){
left=1; right=k-1; des=-(a[i]+b[j]);
while(left<=right){
mid=(left+right)/2;
if(c_add_d[mid]==des){
ans++;
for(l=mid+1; l<=k-1; l++){
if(c_add_d[l]==des){
ans++;
}
else{
break;
}
}
for(l=mid-1; l>=1; l--){
if(c_add_d[l]==des){
ans++;
}
else{
break;
}
}
break;
}
else if(c_add_d[mid]>des){
right=mid-1;
}
else{
left=mid+1;
}
}
}
}
printf("%d\n", ans);
}
return 0;
}