当结果不唯一的时候,使用STL去重的最简单方式是
1 std::sort(res.begin(), res.end()); 2 res.erase(unique(res.begin(), res.end()), res.end());
首先是2Sum题目,构建一个hash表查找数的对应下标,求两个数的和,找到剩余差去hash查找。
https://leetcode.com/problems/two-sum/
1 class Solution { 2 public: 3 vector<int> twoSum(vector<int>& nums, int target) { 4 unordered_map <int,int> mapping; 5 vector<int> result; 6 for(int i=0;i<nums.size();i++) 7 mapping[nums[i]]=i; 8 for(int i=0;i<nums.size();i++) 9 { 10 const int gap=target-nums[i]; 11 if(mapping.find(gap)!=mapping.end() && mapping[gap]>i) 12 { 13 result.push_back(i+1); 14 result.push_back(mapping[gap]+1); 15 } 16 } 17 return result; 18 } 19 };
对于3Sum题目,使用夹逼法,移动两个指针跳过重复的数字。
https://leetcode.com/problems/3sum/
1 class Solution { 2 public: 3 vector<vector<int> > threeSum(vector<int> &num) { 4 vector<vector<int> > res; 5 std::sort(num.begin(), num.end()); 6 for (int i = 0; i < num.size(); i++) { 7 int target = -num[i]; 8 int front = i + 1; 9 int back = num.size() - 1; 10 while (front < back) { 11 int sum = num[front] + num[back]; 12 // Finding answer which start from number num[i] 13 if (sum < target) 14 front++; 15 else if (sum > target) 16 back--; 17 else { 18 res.push_back({num[i],num[front],num[back]}); 19 // Processing duplicates of Number 2 20 // Rolling the front pointer to the next different number forwards 21 front++; 22 while (front < back && num[front] == num[front-1]) front++; 23 // Processing duplicates of Number 3 24 // Rolling the back pointer to the next different number backwards 25 back--; 26 while (front < back && num[back] == num[back+1]) back--; 27 } 28 } 29 // Processing duplicates of Number 1 30 while (i + 1 < num.size() && num[i + 1] == num[i]) i++; 31 } 32 return res; 33 } 34 };
对于4Sum题目,首先可以使用夹逼法,可以看出这个可以推广到NSum,另外可以结合hash进行搜索。
https://leetcode.com/problems/4sum/
1 class Solution { 2 public: 3 vector<vector<int> > fourSum(vector<int> &num, int target) { 4 vector<vector<int> > res; 5 if (num.empty()) 6 return res; 7 std::sort(num.begin(),num.end()); 8 for(int i=0;i<num.size();i++) 9 { 10 int target_3 = target - num[i]; 11 for(int j=i+1;j<num.size();j++) 12 { 13 int target_2 = target_3 - num[j]; 14 int front = j+1; 15 int back = num.size() - 1; 16 17 while(front < back) 18 { 19 int two_sum=num[front]+num[back]; 20 if(two_sum < target_2){ 21 front ++; 22 } 23 else if (two_sum > target_2){ 24 back --; 25 } 26 else{ 27 res.push_back({num[i],num[j],num[front],num[back]}); 28 front++; 29 back--; 30 // Processing the duplicates of number 3 31 while(front < back && num[front]==num[front-1]) front++; 32 // Processing the duplicates of number 4 33 while(front < back && num[back]==num[back+1]) back--; 34 } 35 } 36 // Processing the duplicates of number 2 37 while(j + 1 < num.size() && num[j + 1] == num[j]) ++j; 38 } 39 // Processing the duplicates of number 1 40 while(i + 1 < num.size() && num[i + 1] == num[i]) ++i; 41 } 42 return res; 43 } 44 };
1 class Solution { 2 public: 3 vector<vector<int>> fourSum(vector<int>& num, int target) { 4 vector<vector<int>> result; 5 if (num.size() < 4) return result; 6 sort(num.begin(), num.end()); 7 8 unordered_map<int,vector<pair<int,int> > > cache; 9 10 for(int a=0;a<num.size();a++) 11 { 12 for(int b=a+1;b<num.size();b++) 13 { 14 cache[num[a]+num[b]].push_back(pair<int,int>(a,b)); 15 } 16 } 17 18 for(int c=0;c<num.size();c++) 19 { 20 for(int d=c+1;d<num.size();d++) 21 { 22 int key=target-num[c]-num[d]; 23 if(cache.find(key) == cache.end()) continue; 24 const auto& vec = cache[key]; 25 for(int k=0;k<vec.size();++k) 26 { 27 if(c<=vec[k].second) 28 { 29 continue; 30 } 31 result.push_back( {num[vec[k].first],num[vec[k].second],num[c],num[d]} ); 32 } 33 } 34 } 35 sort(result.begin(), result.end()); 36 result.erase(unique(result.begin(), result.end()), result.end()); 37 return result; 38 } 39 };
参考解答
灵魂机器leetcode解答https://github.com/soulmachine/leetcode
https://leetcode.com/discuss/27198/solution-explanation-comparison-problem-easy-understand
https://leetcode.com/discuss/23595/share-my-solution-around-50ms-with-explanation-and-comments