题目:
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
从给定的数组中找到四个元素之和为target的组合,保存之后返回。要求a ≤ b ≤ c ≤ d,结果集中不包含有重复组合。
思路一:
先排序,然后左右夹逼,复杂度O(n3),会超时。
可以用一个hashmap 先缓存两个数的和,最终复杂度O(n3)。这个策略也适用于3Sum 。
代码:176ms
class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<vector<int>> result; auto last = nums.end(); if(nums.size()<4){ return result; } sort(nums.begin(), nums.end()); for(auto a=nums.begin(); a<prev(last, 3); ++a){ for(auto b=next(a); b<prev(last, 2); ++b){ auto c = next(b); auto d = prev(last); while(c<d){ if(*a+*b+*c+*d<target){ ++c; }else if(*a+*b+*c+*d>target){ --d; }else{ result.push_back({*a, *b, *c, *d}); ++c; --d; } } } } sort(result.begin(), result.end()); result.erase(unique(result.begin(), result.end()), result.end()); return result; } };思路二:
map 做缓存, 用一个hashmap 先缓存两个数的和
// 时间复杂度,平均O(n^2),最坏O(n^4),空间复杂度O(n^2).
代码:236ms
class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<vector<int>> result; if(nums.size()<4){ return result; } sort(nums.begin(), nums.end()); unordered_map<int, vector<pair<int, int>>> cache; for(size_t a=0; a<nums.size(); ++a){ for(size_t b=a+1; b<nums.size(); ++b){ cache[nums[a]+nums[b]].push_back(pair<int, int>(a, b)); } } for(int c=0; c<nums.size(); ++c){ for(int d=c+1; d<nums.size(); ++d){ const int key = target-nums[c]-nums[d]; if(cache.find(key)==cache.end()) continue; const auto& vec = cache[key]; for(size_t k=0; k<vec.size(); ++k){ if(c<=vec[k].second) continue; result.push_back({nums[vec[k].first], nums[vec[k].second], nums[c], nums[d]}); } } } sort(result.begin(), result.end()); result.erase(unique(result.begin(), result.end()), result.end()); return result; } };思路三:
同样适用的是夹逼方法,主要是排除了很多其他浪费时间的因素。最快的方法。
代码:16ms
class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<vector<int>> result; int n = nums.size(); if(nums.size()<4){ return result; } sort(nums.begin(), nums.end()); for(int i=0; i<n-3; i++){ if(i>0 && nums[i]==nums[i-1]) continue; if((nums[i]+nums[i+1]+nums[i+2]+nums[i+3])>target) break; if((nums[i]+nums[n-3]+nums[n-2]+nums[n-1])<target) continue; for(int j=i+1; j<n-2; j++){ if(j>i+1 && nums[j]==nums[j-1]) continue; if((nums[i]+nums[j]+nums[j+1]+nums[j+2])>target) break; if((nums[i]+nums[j]+nums[n-2]+nums[n-1])<target) continue; int left = j+1; int right = n-1; while(left<right){ int sum = nums[left]+nums[right]+nums[i]+nums[j]; if(sum<target){ left++; }else if(sum>target){ right--; }else{ result.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]}); do{ left++; }while(nums[left]==nums[left-1] && left<right); do{ right--; }while(nums[right]==nums[right+1] && left<right); } } } } return result; } };