双指针——三数之和模板

本文详细介绍了使用滑动窗口和双指针技术解决LeetCode中的一系列数组和问题,包括三数之和、最接近的三数之和、较小的三数之和、四数之和、小于K的两数之和以及两数之和的解题模板和关键代码实现,涵盖了数组排序、去重复元素、双指针移动等核心技巧。

滑动窗口——三数之和模板汇总题单:
LC15. 三数之和 https://leetcode.cn/problems/3sum/
LC16. 最接近的三数之和 https://leetcode.cn/problems/3sum-closest/
LC259. 较小的三数之和 https://leetcode.cn/problems/3sum-smaller/
LC18. 四数之和 https://leetcode.cn/problems/4sum/
LC1099. 小于 K 的两数之和 https://leetcode.cn/problems/two-sum-less-than-k/
LC1. 两数之和 https://leetcode.cn/problems/two-sum/

三数之和代码模板

用三数之和做模板
知识点:数组排序,去重复的数字,双指针
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums, int target) {
        int n = nums.size();
        //先对数组排序
        sort(nums.begin(), nums.end());
        
        for (int i = 0; i < n; i++)
        {
            //出现重复元素,去掉该元素
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            //双指针,左指针代表元素最小,右指针代表元素最大,向中间缩进
            int j = i + 1, k = n - 1;
            while (j < k)
            {
                //防止数据外溢,用long long定义数据类型
                long long sum = 0LL + nums[i] + nums[j] + nums[k];
                if (sum == target)
                {
                    //res.push_back({nums[i], nums[j], nums[k]});
                    res.push_back(vector<int>{nums[i], nums[j], nums[k]});          
                    //将符合答案要求的元素放入结果中,双指针开始移动。左指针右移,右指针左移
                    ++j;
                    --k;
                    //左指针遇到重复元素,右移
                    while (j < k && nums[j] == nums[j - 1]) ++j;
                    //右指针遇到重复元素,左移。
                    while (j < k && nums[k] == nums[k + 1]) --k;
                } 
                //当元素之和sum小于目标值时,左指针右边移;元素之后sum大于目标值时,右指针左移。
                else if (sum < target) ++j;
                else --k;   
            }
        }
        return res;
    }
};

LC15. 三数之和 https://leetcode.cn/problems/3sum/

#双指针
LC 15 三数之和
知识点:数组排序,去重复的数字,双指针
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());

        for (int i = 0; i < n; i++)
        {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            int j = i + 1, k = n - 1;
            while (j < k)
            {
                long long sum = 0LL + nums[i] + nums[j] + nums[k];
                if (sum == 0)
                {
                    //res.push_back({nums[i], nums[j], nums[k]});
                    res.push_back(vector<int>{nums[i], nums[j], nums[k]});
                    ++j;
                    --k;
                    while (j < k && nums[j] == nums[j - 1]) ++j;
                    while (j < k && nums[k] == nums[k + 1]) --k;
                } 
                else if (sum < 0) ++j;
                else --k;   
            }
        }
        return res;
    }
};

LC16. 最接近的三数之和 https://leetcode.cn/problems/3sum-closest/

#双指针
LC 16 最接近的三数之和
class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int n = nums.size(); 
        sort(nums.begin(), nums.end()); //数组排序,从小到大
        
        int res = nums[0] + nums[1] + nums[2]; //初始化最开始的三数之和
        for (int i = 0; i < n; i++)
        {
            if (i > 0 && nums[i] == nums[i - 1]) continue; //遇到重复的值跳过

            int j = i + 1, k = n - 1; //双指针,滑动窗口开始收缩
            while (j < k) 
            {
                int sum = nums[i] + nums[j] + nums[k]; 
                //判断最开始的三数之和res与滑动窗口中的三数之和sum进行与目标值比较,更新res。
                if (abs(sum - target) < abs(res - target)) res = sum;
                else if (sum > target) --k; //while (j < k && nums[k] == nums[k + 1]) --k; 可加可不加
                else if (sum < target) ++j; //while (j < k && nums[j] == nums[j - 1]) ++j; 可加可不加
                else if (sum == target) return res;
            }
        }
        return res;
    }
};

LC259. 较小的三数之和 https://leetcode.cn/problems/3sum-smaller/

#双指针
LC 259 较小的三数之和
知识点:数组排序,双指针
class Solution {
public:
    int threeSumSmaller(vector<int>& nums, int target) {
        int n = nums.size();
        sort(nums.begin(), nums.end());

        int cnt = 0;
        for (int i = 0; i < n - 2; i++)
        {
            int j = i + 1, k = n - 1;
            while (j < k)
            {
                int sum = nums[i] + nums[j] + nums[k];
                if (sum < target)
                {
                    cnt += k - j;
                    ++j;
                }
                else
                {
                    --k;
                }
            }
        }
        return cnt;
    }
};

LC18. 四数之和 https://leetcode.cn/problems/4sum/

#双指针
LC 18 四数之和
知识点:同三数之和
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int n = nums.size();
        vector<vector<int>> res;
        if (n < 4) return res;
        sort(nums.begin(), nums.end());

        for (int i = 0; i < n - 3; i++)
        {
            if (i > 0 && nums[i] == nums[i - 1]) continue;

            for (int j = i + 1; j < n - 2; j++)
            {
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;

                int k = j + 1, l = n - 1;
                while (k < l)
                {
                    long long sum = 0LL+ nums[i] + nums[j] + nums[k] + nums[l];
                    if (sum == target)
                    {
                        res.push_back({nums[i], nums[j], nums[k], nums[l]});
                        ++k;
                        --l;
                        while (k < l && nums[k] == nums[k - 1]) ++k;
                        while (k < l && nums[l] == nums[l + 1]) --l; 
                    }
                    else if (sum > target)
                    {
                        --l;
                    }
                    else if (sum < target)
                    {
                        ++k;
                    }
                }
            }
        }
        return res;
    }
};

LC1099. 小于 K 的两数之和 https://leetcode.cn/problems/two-sum-less-than-k/

#双指针
LC 1099 小于K的两数之和
知识点:
class Solution {
public:
    int twoSumLessThanK(vector<int>& nums, int k) {
        int n = nums.size(), res = -1;
        
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                if (nums[i] + nums[j] < k)
                {
                    res = max(res, nums[i] + nums[j]);
                }
            }
        }
        return res;
    }
};

LC1. 两数之和 https://leetcode.cn/problems/two-sum/

LC 1。两数之和
知识点:哈希表
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> map;
        int n = nums.size();

        for (int i = 0; i < n; i++)
        {
            map[nums[i]] = i;
        }

        for (int i = 0; i < n; i++)
        {
            //map[target - nums[i]] != i 防止目标值是当前值的nums[i]的两倍
            if (map.count(target - nums[i]) && map[target - nums[i]] != i)
            {
                return {i, map[target - nums[i]]};
            }
        }
        return {};
    }
};

或者一遍哈希表
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> map;
        int n = nums.size();

        for (int i = 0; i < n; i++)
        {
            if (map.count(target - nums[i]))
            {
                return {i, map[target - nums[i]]};
            }
            map[nums[i]] = i;
        }
        return {};
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值