两数之和

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;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容