题意:
给定一个整数数组 A
,以及一个整数 target
作为目标值,返回满足 i < j < k
且 A[i] + A[j] + A[k] == target
的元组 i, j, k
的数量。
思路1:
三数之和为一定值,一般的方法是统计前两数之和,然后遍历第三个数,并且二分前面存和的数组。
这里对于相同的元素不好处理,所以简单的第一想法是,平方遍历前两个数,二分第三个数。分析复杂度似乎也行。
可是最后一个样例超时了。。。
代码1:
int threeSumMulti(vector<int>& A, int target) {
int sz = A.size();
int mod = 1e9+7;
sort(A.begin(),A.end());
long long sum = 0;
for(int i=0;i<sz;i++){
for(int j=0;j<i;j++){ //枚举前两个数
int aa = target - A[i] - A[j];
int up = upper_bound(A.begin(),A.end(),aa) - A.begin()-1; //二分第三个数,注意重复值
int low = lower_bound(A.begin(),A.end(),aa) - A.begin()-1;
int ma = max(low,i);
if(up>ma){
sum+=up-ma;
sum=sum%mod;
}
}
}
return sum;
}
思路2:
基于前一种思路,依旧遍历前两个值,不过因为前两个值确定了,我们可以记录下他们的和,以及用一个map来存储某一个和x有多少个。然后在以后的遍历过程中,遇到某一个值A[i],在map中找到与其相对应的和的个数。使得A[I] + x ==target.
代码2:
int threeSumMulti(vector<int>& A, int target) {
unordered_map<int,int>ma;
int mod = 1e9+7;
int sz = A.size();
long long sum = 0;
for(int i=0;i<sz;i++){
sum = (sum+ma[target-A[i]])%mod;
for(int j=0;j<i;j++){
++ma[A[i]+A[j]];
}
}
return sum%mod;
}
思路3:
观察一下,A[i]的取值范围只有100,而长度确有3000,也就是说,一个明显的提示就是去重。去重之后再用第一种二分的方法就行了,甚至三重循环也可。不过这不仅仅是简单的去重,我们得记录重复值个数。根据重复值个数我们可以算出在A[i],A[j],A[k]取相同值的时候的数量。
代码3:
class Solution {
public:
int threeSumMulti(vector<int>& A, int target) {
long long ch[105];
int mod = 1e9+7;
memset(ch,0,sizeof(ch));
for(int i=0;i<A.size();i++)ch[A[i]]++;
sort(A.begin(),A.end());
vector<int>::iterator index = unique(A.begin(),A.end());
A.erase(index,A.end());
int sz = A.size();
long long sum = 0;
for(int i=0;i<=100;i++){
for(int j=i;j<=100;j++){
int k = target - i-j;
if(k<i||k<j||k>100||ch[i]==0||ch[j]==0||ch[k]==0)continue;
if(i==j&&j==k){
if(ch[i]>=3)sum = (sum+(ch[i]*(ch[i]-1)*(ch[i]-2))/6)%mod;
}
else if(i==j&&ch[i]>=2){
int ma = (ch[i]*(ch[i]-1)*ch[k])/2;
sum = (sum+ma)%mod;
// cout<<ma<<endl;
}
else if(k==i&&ch[k]>=2){
int ma = (ch[i]*(ch[i]-1)*ch[j])/2;
sum = (sum+ma)%mod;
}
else if(k==j&&ch[k]>=2){
int ma = (ch[k]*(ch[k]-1)*ch[i])/2;
sum = (sum+ma)%mod;
}
else if(i!=j&&j!=k&&i!=k){
sum = (sum+ch[i]*ch[j]*ch[k])%mod;
}
//cout<<i<<" "<<j<<" "<<k<<" "<<sum<<endl;
}
}
return sum%mod;
}
};