LeetCode 923. 三数之和的多种可能(机智题 三种解法)

题意:

给定一个整数数组 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;
}

};

猜你喜欢

转载自blog.csdn.net/lwgkzl/article/details/83151241
今日推荐