力扣双指针算法题目:双数之和,三数之和,四数之和

目录

一:双数之和

1.题目:

2.思路解析

3.代码

二:三数之和

1.题目

2.思路解析

3,代码

三:四数字之和

1.题目

2.思路解析

3.代码


一:双数之和

1.题目:

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使他们的和正好是s,如果有多对数字的和是s,则输出一对即可

2.思路解析

这个题目要求检索数组中两个数字的和为s,那么就需要使用双指针去遍历这个数组,每遍历一次,就和s对比一下

暴力求解就是枚举法,时间复杂度太大了,这里不过多赘述

如果是稍微巧妙一点的解法,便是将left初始化放在数组最左边,right最右边,然后二者向着中间遍历,

一边遍历一边对left和right所指向的数字求和(sum),并且和目标值target对比,

如果比target小,那么就是小的数字(left)太小了,那么就需要left++,

如果比target大,那么就是大的数字太大了,就需要right--

3.代码

至于题目中的要求“如果有多对数字的和是s,则输出一对即可”,这句话的意思就是要“去重”,在STL中,我们可以直接使用容器“set”直接去重,至于如何手搓轮子,请向下看

二:三数之和

1.题目

2.思路解析

总而言之就是双指针的思维基础下又在上面套了一层循环

a.先将无需数组排列成有序数组

b. 双指针:cur自左向右遍历,cur对数组的遍历作为最外层的循环,本体中,我们的target=0

所以需要三个数字和为0,那么left和right所指向的数字的和必然是cur所指向的数字的相反数

由于是有序数组,具有单调性,如果cur>0,那么后面必然是正数,此情况便可以排除

c:去重操作:

left去重:left向右移动一格,如果和上一个数字相同,那么便skip

right去重:right向左移动一格,如果和上一个数字相同,那么skip

cur去重:cur向右走,每次向右都要注意越界(left<right)

d:cur++是最外层的循环。

3,代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        vector<vector<int>> ret;
        sort(nums.begin(), nums.end());

        int n = nums.size();
        int cur = 0;
       while(cur<n)
       {
           int left = cur + 1, right = n - 1;
           int target = -nums[cur];
           while (left < right)
           {
               int sum = nums[left] + nums[right];

               if (nums[cur] > 0) break;
               if (sum < target)
               {left++;}
               else if (sum > target)
               {right--;}
               else
               {
                   ret.push_back({ nums[cur],nums[left],nums[right] });
                   left++;
                   right--;

                   while (left < right && nums[left] == nums[left - 1]) { left++; }
                   while (left < right && nums[right] == nums[right + 1]) { right--; }
               }
           }
           cur++;
           while (cur < nums.size() && nums[cur] == nums[cur - 1]) { cur++; }
       }
        return ret;
    }
};

总结:三数之和的大体思路就是

首先明确一点最后要转换成双指针

因为需要找到三个数字之和为target

所以先将cur固定住,再另外两个数字(双指针操作)和为target-cur

三:四数字之和

1.题目

. - 力扣(LeetCode)

2.思路解析

这个四数之和的思路不能说和三数之和类似,只能说是一摸一样的,不管几个数字,其核心思路都是最开始的双数之和

如果要将四数之和变成双指针双数之和思想,那么和三数之和一样,将双数之和外套两个循环

仍然是双指针遍历相加然后和target进行对比

3.代码

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) 
    {
        vector<vector<int>> ret;
        sort(nums.begin(),nums.end());
        int n=nums.size();

        int a=0;
        while(a<n)
        {
            int b=a+1;
            while(b<n)
            {
                long long aim=(long long)target-(long long)nums[a]-(long long)nums[b];
                int left=b+1,right=n-1;
                while(left<right)
                {
                    int sum=nums[left]+nums[right];
                    if(sum<aim) {left++;}
                    else if(sum>aim) {right--;}
                    else
                    {
                        ret.push_back({nums[a],nums[b],nums[left],nums[right]});
                        left++; right--;
                        while(left<right&&nums[left]==nums[left-1]) {left++;}
                        while(left<right&&nums[right]==nums[right+1]) {right--;}
                    }
                }
                b++;
                while(b<n&&nums[b]==nums[b-1]) {b++;}
            }
            a++;
            while(a<n&&nums[a]==nums[a-1]) {a++;}
        }
        return ret;
    }
};

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值