题解:
这道题有很多方法,我在LeetCode上做过这道题,由于时间长,只是隐约记到大概思路,后来还是将原来的做法翻出来看明白,重新将这道题做了,题多而不去弄懂每道题的精髓和本质,实际上和浪费时间没有区别,所以总结下一下,由于这道题有很多解法,只写一种,后续来补。
这道题首先要用到哈希表,也就是map来存,我一开始做的时候遇到了不少的坑,比如-1 2 -3 2这种,我一直想着如果遇到1 -3和2 2的组合,是否还需要特殊处理之类的问题,凡是四个数可以相加为0的,肯定会有这种-1 2和-3 2的组合,所以只需要顺序考虑即可。
首先预处理排序,然后求所有不重合的两个数相加的组合,用map保存起来,键为和,值为vector<pair<int,int>>,保存两个值的索引,比如五个数,预处理一共要执行4 + 3 + 2 + 1,由此可知,pair中的两个索引也是顺序,以便后面二分查找。
预处理完后,双重循环遍历,对于两个数而言a,b,则查找值就为0-a-b,如果查找到了,就对它的值进行二分查找,索引均要大于第二个数的索引,如果查找到了,那么这两个数必然和a,b的索引是不相同,这样就可以得到四个数为0的情况。
AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <queue>
#define MAX_INF 0x3f3f3f
#define ll long long
#define ull unsigned long long
const int MAXN = 2e5+10;
const int MOD = 1e9+7;
using namespace std;
#define CLR(a, b) memset((a), (b),sizeof((a)))
#define srt(v) sort(v.begin(),v.end())
#define grtsrt(v) sort(v.begin(),v.end(),greater<ll>())
#define mnv(v) *min_element(v.begin(),v.end())
#define mxv(v) *max_element(v.begin(),v.end())
#define G_priority_queue(v, w) priority_queue<v, vector<v>, greater<v> > w
#define L_priority_queue(v, w) priority_queue<v, vector<v>, less<v> > w
#define For_equal(p ,s, e) for(p = s;p <= e;p++)
#define For_nonequal(p, s, e) for(p = s;p < e;p++)
//ll dp[MAXN];
//ll a[1005][1005];
ll b[1005];
int main(){
int n, m;
int i, j, k;
ll t;
int cnt = 0;
ll sum = 0;
ll miv,mav;
int flag = 0;
map<ll, vector<pair<int, int>>> record;
cin>>n;
for(i = 0 ; i < n ; ++i)
cin>>b[i];
sort(b, b+n);
for(i=0;i<n-1;i++){
for(j=i+1;j<n;++j){
record[b[i]+b[j]].push_back(make_pair(i, j));
}
}
for(i=0;i<=n-4;++i){
for(j=i+1;j<=n-3;++j){
t = 0 - b[i] - b[j];
if(b[j+1] + b[j+2] > t || b[n-1] + b[n-2] < t)
continue;
if(record.find(t) == record.end())
continue;
vector<pair<int, int>>::iterator iter = lower_bound(record[t].begin(),
record[t].end(), make_pair(j+1, j+1));
if(iter != record[t].end()){
//cout<< b[i] << " " << b[j] << " " << b[iter->first] <<" " << b[iter->second]<<"\n";
flag = 1;
break;
}
}
if(flag)
break;
}
if(flag)
cout<<"Yes"<<"\n";
else
cout<<"No"<<"\n";
return 0;
}
AC代码:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int n = nums.size();
vector<vector<int>> res;
if ( n < 4 )
return res;
sort( nums.begin(), nums.end() );
unordered_map<int, vector<pair<int, int>>> record;
for ( int i = 0 ; i < n - 1 ; i = next_index(nums, i) )
for ( int j = i + 1 ; j < n; j = next_index(nums, j) )
record[nums[i] + nums[j]].push_back(make_pair(nums[i],nums[j]));
for ( int i = 0 ; i <= n - 4 ; i = next_index(nums, i) ){
for ( int j = i + 1 ; j <= n - 3 ; j = next_index(nums, j) ){
int t = target - nums[i] - nums[j];
if ( nums[j+1] + nums[j+2] > t || nums[n-1] + nums[n-2] < t )
continue;
if ( record.find(t) == record.end() )
continue;
vector<pair<int, int>>::iterator iter = lower_bound(record[t].begin(), record[t].end(),
make_pair(nums[j+1], nums[j+1]));
for ( ; iter != record[t].end() ; iter++ )
res.push_back( {nums[i], nums[j], iter->first, iter->second} );
}
}
return res;
}
private:
int next_index( const vector<int>& nums, int index ){
for ( int i = index + 1 ; i < nums.size() ; i ++ )
if ( nums[index] != nums[i] )
return i;
return nums.size();
}
};