18.求三数之和

题目

链接:leetcode链接

思路分析(双指针)

这道题目与上一道题,求有效三角形的个数,十分类似,都是使用双指针算法来解决问题。

先进行排序,然后利用单调性进行调整,逐步逼近正确答案。

我们先固定一个数,记作target,则只需要寻找两个数,使这两个数的和为负target即可。

不妨将target固定位最大值,将需要的两个数在target的左边区间进行寻找,即在小于target的范围里寻找,这时利用双指针,记作left,right,从两侧向中间逼近即可。

会出现以下三种情况:

a、left + right + target > 0

这说明right大了,需要 --right,继续寻找

b、left + right + target < 0

这说明left小了,需要 ++left,继续寻找

c、left + right + target == 0

符合要求,保存下来,继续寻找,

注意:题目有要求不能重复,所以,我们可以在找到了符合要求的三元组后,跳过相同元素再继续寻找,这样,就可以避免重复的三元组。(当然使用set等去重也可以)

同理,target也需要进行去重。

代码

C++ 复制代码
vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());

        vector<vector<int>> a;
        for(int i = nums.size()-1;i>=2;--i)
        {
            int left = 0,right = i-1;
            while(left < right)
            {
                int sum = nums[left] + nums[right] + nums[i];
                if(sum == 0)
                {
                    a.push_back({nums[left],nums[right],nums[i]});

                    //这两个while是去重
                    while(nums[left] == nums[left + 1] && left < right) ++left;
                    while(nums[right] == nums[right - 1] && left < right) --right;
                    
                    //这个是去完重后寻找下一个三元组
                    left++,right--;//
                }
                else if(sum > 0) --right;
                else ++left;
            }

            //for循环里面已经有一个--i了,这里一个--i就可以去重并且走向下一个三元组
            while(nums[i] == nums[i-1] && i>=3) --i;
        }

        return a;
    }

另一道相似的题----四数之和

方法几乎一样,只是多套一层循环。

这道题目有一点很坑的地方,题目中target是int类型,但是四数之和有可能是超过int类型的范围的,需要强转。

代码附上

C++ 复制代码
 vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());

        vector<vector<int>> a;

        for(int i = nums.size() - 1;i >= 3;--i)
        {
            for(int j = i - 1;j >= 2;--j)
            {
                int left = 0, right = j - 1;

                while(left < right)
                {
                    long long sum = (long long)nums[left] + nums[right] + nums[i] + nums[j];
                    
                    if(sum == (long long)target)
                    {
                        a.push_back({nums[left],nums[right],nums[i],nums[j]});

                        while(nums[left] == nums[left + 1] && left < right)
                        {
                            ++left;
                        }
                        while(nums[right] == nums[right - 1] && left < right)
                        {
                            --right;
                        }
                        ++left;
                        --right;
                    }
                    else if(sum < (long long)target)
                    {
                        ++left;
                    }
                    else
                    {
                        --right;
                    }
                }

                while(nums[j] == nums[j - 1] && j >= 3)
                {
                    --j;
                }
            }
                while(nums[i] == nums[i - 1] && i >= 4)
                {
                    --i;
                }
        }

        return a;
    }
相关推荐
m0_629494732 小时前
LeetCode 热题 100-----17.缺失的第一个正数
数据结构·算法·leetcode
Cando学算法2 小时前
鸽笼原理(抽屉原理)
c++·算法·学习方法
Tisfy2 小时前
LeetCode 0796.旋转字符串:暴力模拟
算法·leetcode·题解·模拟·字符串匹配
BlockChain8882 小时前
AI+区块链深度探索:算法与账本的共生时代
人工智能·算法·区块链
生成论实验室2 小时前
《源·觉·知·行·事·物:生成论视域下的统一认知语法》第一章 源:不可言说的生成之源
人工智能·科技·算法·生活·创业创新
2zcode2 小时前
基于低光照增强与轻量型CNN道路实时识别算法研究(UI界面+数据集+训练代码)
人工智能·算法·cnn·低光照增强·自动驾驶技术
郝学胜-神的一滴3 小时前
跨平台动态库与头文件:从原理到命名的深度解析
linux·c++·程序人生·unix·cmake
代码中介商3 小时前
C++ 仿函数(Functor)深度解析:从基础到应用
开发语言·c++
小雅痞3 小时前
[Java][Leetcode middle] 209. 长度最小的子数组
java·算法·leetcode
王老师青少年编程3 小时前
csp信奥赛C++高频考点专项训练之字符串 --【字符串基础】:[NOIP 2018 普及组] 标题统计
c++·字符串·csp·高频考点·信奥赛·专项训练·标题统计