犹豫不决先排序,步步紧逼双指针---力扣刷题

 

目录

 

第一题:和为s的两个数

第二题:和为0的三个数

第三题:四数之和


 

第一题:和为s的两个数

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

ef9396db7b394c2bb9992c8f4f0669b1.png思路:

法一先想到暴力枚举,即利用两层循环,当两数之和等于目标值的时候返回,

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int n = nums.size();
        for (int i = 0; i < n; i++) { // 第⼀层循环从前往后列举第⼀个数
            for (int j = i + 1; j < n; j++) { // 第⼆层循环从 i 位置之后列举第⼆个
                数
                    if (nums[i] + nums[j] == target) // 两个数的和等于⽬标值,说明我们
                        已经找到结果了
                        return { nums[i], nums[j] };
            }
        }
        return { -1, -1 };
    }
};

法二,由于是升序,这里想到用双指针,一个cur指向第一个元素,dest指向最后一个元素,接着呢判断两数大与target的大小关系,大了right--小了left++,大家可以画图理解,注意是升序排列

class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target)
    {
        int cur = 0, dest = price.size() - 1;
        while (cur < dest)
        {
            if (price[cur] + price[dest] > target)
            {
                dest--;
            }
            else if (price[cur] + price[dest] < target)
            {
                cur++;
            }
            else
                return{ price[cur],price[dest] };
        }
        return { 1,1 };
    }
    
};

第二题:和为0的三个数

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

a35cef13bcb14e199b7dc30bc0556ef3.png思路:

第一思路还是暴力枚举,即三层循环然后满足条件储存接着用set容器来去重,但会超时,这里利用上题的一个思路,即还是双指针,我们可以先排好序然后,固定一个数,然后开始从固定数的后一个数进行查找如果两外两个数等于固定数的相反数就存入,关键是如何去重。

去重的核心来源于有重复的固定数以及重复的双指针所指向的数,因此我们如果把双指针所指向的数进行处理,那么即可达到去重,并且有一点区别的是不能有重复的,和不能有遗漏,那么当找到一组数据时,应该继续寻找,直到两个指针之间没有元素。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {//下标不相等,并且和为0
        vector<vector<int>>arr;
        sort(nums.begin(),nums.end());
        int n=nums.size();
        for(int i=0;i<n;)
        {
            //固定一个
            int left=i+1,right=n-1,target=-nums[i];
            if(nums[i]>0)break;
            while(left<right)
            {
                int sum=nums[left]+nums[right];
                //只要两个之间还有元素
                if(target<sum)right--;
                else if(target>sum)left++;
                else 
            {
                arr.push_back({nums[i],nums[left],nums[right]});
                left++,right--;
                //去重
                while(left<right&&nums[left]==nums[left-1]) left++;
                while(left<right&&nums[right]==nums[right+1] right--;
            }
            }
            i++;
            while(i<n&&nums[i]==nums[i-1]) i++;
        }
        return arr;
    }
};

第三题:四数之和

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

d66e7391d30f4225804fc86a79642841.png思路:

承接上题,这里我们只需同时固定两个数,再判断另外两个数和这两个数和是否相等,以及两层去重即可

由于num[i]的值较大,因此这里对数据处理用long long 的数据类型

class Solution
{
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target)
    {
        vector<vector<int>> ret;
        // 1. 排序
        sort(nums.begin(), nums.end());
        // 2. 利⽤双指针解决问题
        int n = nums.size();
        for (int i = 0; i < n; ) // 固定数 a
        {
            // 利⽤ 三数之和
            for (int j = i + 1; j < n; ) // 固定数 b
            {
                // 双指针
                int left = j + 1, right = n - 1;
                long long aim = (long long)target - nums[i] - nums[j];
                while (left < right)
                {
                    int sum = nums[left] + nums[right];
                    if (sum < aim) left++;
                    else if (sum > aim) right--;
                    else
                    {
                        ret.push_back({ nums[i], nums[j], nums[left++],
                       nums[right--] });
                        // 去重⼀
                        while (left < right && nums[left] == nums[left - 1])
                            left++;
                        while (left < right && nums[right] == nums[right + 1])
                            right--;
                    }
                }
                // 去重⼆
                j++;
                while (j < n && nums[j] == nums[j - 1]) j++;
            }
            // 去重三
            i++;
            while (i < n && nums[i] == nums[i - 1]) i++;
        }
        return ret;
    }
};

 

 

 

评论 108
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值