LeetCode 923. 三數之和的多種可能(機智題 三種解法)
阿新 • • 發佈:2018-11-21
題意:
給定一個整數陣列 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; } };