【每日刷题】Day103

【每日刷题】Day103

🥕个人主页:开敲🍉

🔥所属专栏:每日刷题🍍

🌼文章目录🌼

1. LCR 007. 三数之和 - 力扣(LeetCode)

2. 18. 四数之和 - 力扣(LeetCode)

3. 209. 长度最小的子数组 - 力扣(LeetCode)

1. LCR 007. 三数之和 - 力扣(LeetCode)

//思路:双指针。

//本题的思路确实难想,但是本题的重点不在于思路,而是在于细节的处理。

class Solution {

public:

    vector<vector<int>> threeSum(vector<int>& nums)

    {

        vector<vector<int>> ans;

//按照升序排序

        sort(nums.begin(),nums.end());

        int n = nums.size();

//for循环,i作为每次固定位置的下标

        for(int i = 0;i<n;)

        {

//小优化,如果nums[i]已经>0了,那么后面的数也一定是>0的,则不可能有 == 0 的三元组。

            if(nums[i]>0) break;

//left、right作为区间,target为固定值的相反数

            int left = i+1,right = n-1,target = -nums[i];

            while(left<right)

            {

                int sum = nums[left]+nums[right];

//右边数太大,right--

                if(sum>target) right--;

//左边数太小,left++

                else if(sum<target) left++;

//找到三元组,将三元组计入答案中,进行细节处理

                else

                {

                    ans.push_back({nums[left],nums[right],nums[i]});

                    left++;

                    right--;

//如果left遍历到与left-1相同的数,则必定会组成重复的三元组,直接跳过,同时需要防止越界

                    while(left<right&&nums[left]==nums[left-1]) left++;

//如果right遍历到与right+1相同的数,同上,直接跳过。

                    while(left<right&&nums[right]==nums[right+1]) right--;

                }

            }

//先让i++往下遍历

            i++;

//如果i遍历到与i-1相同的数,与上述相同,直接跳过

            while(i<n&&nums[i]==nums[i-1]) i++;

        }

        return ans;

    }

};

2. 18. 四数之和 - 力扣(LeetCode)

//思路:与三数之和类似,区别在于三数之和是排序后固定一个数,而四树之和排序后固定两个数。

class Solution {

public:

    vector<vector<int>> fourSum(vector<int>& nums, int target)

    {

        vector<vector<int>> ans;

        int n = nums.size();

        sort(nums.begin(),nums.end());

//两个for循环固定两个数

        for(int i = 0;i<n-3;)

        {

            for(int j = i+1;j<n-2;)

            {

                int left = j+1;

                int right = n-1;

//left和right双指针在区间内遍历查找

                while(left<right)

                {

//剩下步骤与 "三数之和" 一样

                    long long val_left = nums[left],val_right = nums[right],val_i = nums[i],val_j = nums[j];

                    long long sum = val_left+val_right+val_i+val_j;

                    if(sum>target)

                        right--;

                    else if(sum<target)

                        left++;

                    else

                    {

                        ans.push_back({nums[i],nums[j],nums[left],nums[right]});

                        left++;

                        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 ans;

    }

};

3. 209. 长度最小的子数组 - 力扣(LeetCode)

//思路:滑动窗口。滑动窗口是什么?上图

class Solution {

public:

    int minSubArrayLen(int target, vector<int>& nums)

    {

        int left = 0;

        int right = -1;

//sum记录left与right区间内值的和

        int sum = 0;

//ans用于记录最小长度

        int ans = 10000000;

        while(right!=nums.size())

        {

//如果小于目标值,则当前子数组不符合,right继续遍历,left不动

            if(sum<target)

            {

                right++;

//防止越界

                if(right==nums.size())

                    break;

//记录区间和

                sum+=nums[right];

            }

            else

            {

//记录最小长度

                ans = ans<(right-left+1)?ans:(right-left+1);

//记录left当前值

                int tmp = nums[left];

                left++;

//left向左移动,sum-=tmp

                sum-=tmp;

            }

        }

//如果没有找到符合题意的子数组则返回0

        if(ans==10000000)

            ans = 0;

        return ans;

    }

};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值