1. 程式人生 > >LeetCode 923. 三數之和的多種可能(機智題 三種解法)

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;
}

};