n数求和,固定n-2个数,最后两个数在连续区间内一左一右根据当前求和与目标值比较移动,如果sum<target,移动较小数,否则,移动较大数
重复数处理:
使i为左至右第一个不重复数:while(i != 0 && i<n-2 && a[i] == a[i-1]) i++;
使r为右至左第一个不重复数(原序最后一个):while(r>i && r+1<n && a[r] == a[r+1]) r--;
15. 3Sum
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { sort(nums.begin(), nums.end()); vector<vector<int>> ans; int n = nums.size(); vector<int> &a = nums; for(int i=0; i<n-2; i++) { while(i != 0 && i<n-2 && a[i] == a[i-1]) i++; int l = i+1, r = n-1; while(l < r) { int s = a[i]+a[r]+a[l]; if(s == 0) { ans.push_back({a[i], a[l], a[r]}); l++; r = n-1; while(l<r && a[l] == a[l-1]) l++; } else if(s < 0) { l++; while(l<r && a[l] == a[l-1]) l++; } else { r--; while(r>i && r+1<n && a[r] == a[r+1]) r--; } } } return ans; } };
16. 3Sum Closest
class Solution { public: int threeSumClosest(vector<int>& nums, int target) { sort(nums.begin(), nums.end()); int n = nums.size(); int mind = INT_MAX, ans = 0; vector<int> &a = nums; for(int i=0; i<n-2; i++) { int l = i+1, r = n-1; while(l < r) { int s = a[i]+a[r]+a[l]; int d = abs(s - target); if(s == target) return s; else if(d < mind) { mind = d; ans = s; } if(s < target) l++; else r--; } } return ans; } };
18. 4Sum
class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<int> &a = nums; sort(a.begin(), a.end()); vector<vector<int>> ans; int n = a.size(); if(n < 4) return ans; for(int i=0; i<n-3; i++) { while(i != 0 && i<n-3 && a[i] == a[i-1]) i++; for(int j=i+1; j<n-2; j++) { while(j != i+1 && j<n-2 && a[j] == a[j-1]) j++; int l = j+1, r = n-1; while(l < r) { int s = a[i]+a[j]+a[r]+a[l]; if(s == target) { ans.push_back({a[i], a[j], a[l], a[r]}); l++; r = n-1; while(l<r && a[l] == a[l-1]) l++; } else if(s < target) { l++; while(l<r && a[l] == a[l-1]) l++; } else { r--; while(r>j && r+1<n && a[r] == a[r+1]) r--; } } } } return ans; } };