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=; i<n-; i++) {
while(i != && i<n- && a[i] == a[i-]) i++;
int l = i+, r = n-;
while(l < r) {
int s = a[i]+a[r]+a[l];
if(s == ) {
ans.push_back({a[i], a[l], a[r]});
l++; r = n-;
while(l<r && a[l] == a[l-]) l++;
} else if(s < ) {
l++;
while(l<r && a[l] == a[l-]) l++;
} else {
r--;
while(r>i && r+<n && a[r] == a[r+]) 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 = ;
vector<int> &a = nums;
for(int i=; i<n-; i++) {
int l = i+, r = n-;
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 < ) return ans;
for(int i=; i<n-; i++) {
while(i != && i<n- && a[i] == a[i-]) i++;
for(int j=i+; j<n-; j++) {
while(j != i+ && j<n- && a[j] == a[j-]) j++;
int l = j+, r = n-;
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-;
while(l<r && a[l] == a[l-]) l++;
} else if(s < target) {
l++;
while(l<r && a[l] == a[l-]) l++;
} else {
r--;
while(r>j && r+<n && a[r] == a[r+]) r--;
}
}
}
}
return ans;
}
};