1、两数之和 双指针 双for循环 哈希
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int>mp;
for(int i =0;i<nums.size();i++){
auto it = mp.find(target-nums[i]);
if(it !=mp.end()){
return {it->second,i};
}
mp[nums[i]]=i;
}
return {};
}
};
vector<int> twoSum(vector<int>& nums, int target) {
// 先对数组排序
sort(nums.begin(), nums.end());
// 左右指针
int lo = 0, hi = nums.size() - 1;
while (lo < hi) {
int sum = nums[lo] + nums[hi];
// 根据 sum 和 target 的比较,移动左右指针
if (sum < target) {
lo++;
} else if (sum > target) {
hi--;
} else if (sum == target) {
return {nums[lo], nums[hi]};
}
}
return {};
}
三数字之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
vector<int>vec;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++){
if (nums[i] > 0) {
return res;
}
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left =i+1;
int right = nums.size()-1;
while(left < right){
if(nums[i] +nums[left] + nums[right] < 0){
left++;
} else if (nums[i] +nums[left] + nums[right] > 0) {
right--;
} else{
res.push_back(vector<int>{nums[i], nums[left], nums[right]});
//去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
// 找到答案时,双指针同时收缩
right--;
left++;
}
}
}
return res;
}
};
四数之和
using LL = long long;
class Solution {
public:
// 思路:类比《三数之和》,先排序,然后枚举并固定a b,利用首尾指针寻找 c d
vector<vector<int>> fourSum(vector<int>& nums, int x) {
if(nums.size()<4)return {};
vector<vector<int>> res;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size()-3;++i){
// 由于nums[i]对应的元素值已经枚举过了,不需要再次枚举了
if(i>0&&nums[i]==nums[i-1])continue;
// 以下代码与 三数之和 一样
for(int j=i+1;j<nums.size()-2;++j){
// 由于nums[i]对应的元素值已经枚举过了,不需要再次枚举了
if(j>i+1&&nums[j]==nums[j-1])continue;
// 首尾指针来寻找c d
int l=j+1,r=nums.size()-1;
while(l<r){
LL sum=0LL+nums[i]+nums[j]+nums[r]+nums[l];
if(sum>x)r--;// sum太大,向左逼近
else if(sum<x)l++;// sum太小,向右逼近
else{
// 添加结果
res.push_back({nums[i],nums[j],nums[l],nums[r]});
// 缩小区间
l++,r--;
while(l<r&&nums[l]==nums[l-1])l++;
while(l<r&&nums[r]==nums[r+1])r--;
}
}
}
}
return res;
}
};
n数之和
/* 注意:调用这个函数之前一定要先给 nums 排序 */
vector<vector<int>> nSumTarget(
vector<int>& nums, int n, int start, int target) {
int sz = nums.size();
vector<vector<int>> res;
// 至少是 2Sum,且数组大小不应该小于 n
if (n < 2 || sz < n) return res;
// 2Sum 是 base case
if (n == 2) {
// 双指针那一套操作
int lo = start, hi = sz - 1;
while (lo < hi) {
int sum = nums[lo] + nums[hi];
int left = nums[lo], right = nums[hi];
if (sum < target) {
while (lo < hi && nums[lo] == left) lo++;
} else if (sum > target) {
while (lo < hi && nums[hi] == right) hi--;
} else {
res.push_back({left, right});
while (lo < hi && nums[lo] == left) lo++;
while (lo < hi && nums[hi] == right) hi--;
}
}
} else {
// n > 2 时,递归计算 (n-1)Sum 的结果
for (int i = start; i < sz; i++) {
vector<vector<int>>
sub = nSumTarget(nums, n - 1, i + 1, target - nums[i]);
for (vector<int>& arr : sub) {
// (n-1)Sum 加上 nums[i] 就是 nSum
arr.push_back(nums[i]);
res.push_back(arr);
}
while (i < sz - 1 && nums[i] == nums[i + 1]) i++;
}
}
return res;
}