【代码随想录刷题记录】LeetCode209长度最小的子数组

题目地址

1. 思路

1.1 基本思路及代码实现

按照卡尔老师的思路,这个题目涉及到了一个重要的知识:滑动窗口,(卡尔老师的图片演示比我做的好,就看卡尔老师的图片演示就行,其中我的fast指针对应卡尔老师的j指针,我的slow指针对应卡尔老师的i指针),所谓滑动窗口和快慢指针差不多,我最开始的想法是这样的:用快慢指针slow和fast遍历这个数组,用一个整型变量sum保存每次子数组的求和结果,为了能够用一次for循环完成整个任务,我们必须在满足sum大于等于target(即题目要求的条件)后就将子数组缩小一个,即sum减去一个nums[slow],然后slow向前移动一个,直到sum不再大于等于target,我们才能够继续探索新的连续子数组(也就是for循环完成一次循环)。然后我们每次遇到符合条件的情况计算一次长度,长度为fast - slow + 1(fast和slow直接的元素个数),然后对比,初始化一个变量叫minlen,它的值是int32的最大值INT32_MAX,相当于一个无穷大,这样方便我们找最小值(如果找最大值,就赋值INT32_MIN),然后就对比,如果minlen没有fast - slow + 1小,就让minlen=fast - slow + 1,否则还是minlen,我们最后求的就是这个符合条件的最小长度的连续子数组的长度,如果没有合适的子数组,我们将返回0(即长度为0),其具体代码实现如下(顺利通过):

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int slow = 0;
        int sum = 0; // 求和用的变量
        // (这个是错解)int len = 0; // 当前子数组的长度
        int minlen = INT32_MAX; //子数组的最小长度
        // slow先停着不动,fast正常遍历
        // sum每次都将fast遍历过的求和的元素保存起来
        // 我最开始的想法是想搞一个单独len变量记录长度
        // 但是这样会出错,假设数组是[1],target=7,根本找不到合适的子数组
        // 如果单独记录len的长度的变化,根据循环的条件
        // 这种情况,sum没有>=target,len是正常++的,也就是最后minlen=1
        // 所以不能用单独的变量len记录子数组长度
        // 子数组的长度其实是fast - slow + 1
        // 每次当sum>=target的时候,才对比minlen和fast - slow + 1
        // 如果某次循环,sum+=nums[fast];的值导致sum>=target
        // 此时刚好满足条件,先计算子数组长度,然后对比是否为最小的长度
        // 然后让sum-=nums[slow],把slow没移动前的元素剔除
        // 这样剔除一个元素后,继续判断(用while循环),直到不符合条件能够接着往下搜索子数组
        // 用while循环而不用if语句的原因是
        // 假设数组为[1,2,3,7,9],target=7,迭代到fast==3就满足了条件
        // 此时剔除slow指向的元素1,然后slow++
        // 新的子数组sum=2+3+7>7,还是满足条件,无法继续搜索子数组
        // 所以只能用while循环一直执行剔除和slow++,对比长度等操作
        // 直到不满足条件可以继续搜索子数组为止
        // 直到外层的for循环迭代结束,我们就遍历了所有符合条件的子数组
        for(int fast = 0; fast < nums.size(); fast++)
        {
            sum+=nums[fast];
            while(sum>=target)
            {
                minlen = min(fast - slow + 1, minlen);
                sum-=nums[slow];
                slow++;
            }
        }
        // minlen没有被赋值的话,说明没有合适条件的子数组
        if(minlen == INT32_MAX)
        {
            return 0;
        }
        return minlen;
    }
};

1.2 关于是用while循环还是if条件

我一开始的想法并没有在for循环里嵌套一个while(sum>=target)来完成这个过程,而是用的if(sum>=target),这就会导致一个问题:

如果数组nums[1, 2, 3, 7, 9],而target = 7,fast一直遍历到fast为3也就是其对应元素为7时,sum = 1 + 2 + 3 + 7 > 7,此时满足了条件,而fast为2时,sum=1 + 2 + 3=6 < 7不满足条件,如果在fast为3时,我们用的是if条件而不是while循环,那么,执行一次后sum减去nums[slow]=nums[0]=1就变成sum = 2 + 3 + 7>7,还是满足条件,但是我们用if只能执行一次,我们要找到不满足条件的时候才能进行下一次循环,所以我们只能用while循环来完成这个过程。

1.3 关于是用变量记录长度,还是用fast - slow + 1代表子数组的长度

我最开始的想法是用一个for循环外的遍历len来记录子数组的长度,fast每次增加,len++,如果不满足条件len--,直到不满足题目要求的条件,但是这样做是错的,比如nums为[1],而target为7,这种情况下,我们永远找不到满足条件的子数组,因为我们永远没法进入while循环条件,因为sum=1<7,所以我们也没法执行len--操作,这样就导致本应该返回0,现在却返回了错误的值1。

相关推荐
py有趣1 小时前
LeetCode算法学习之两数之和 II - 输入有序数组
学习·算法·leetcode
夏鹏今天学习了吗1 小时前
【LeetCode热题100(62/100)】搜索二维矩阵
算法·leetcode·矩阵
吃着火锅x唱着歌3 小时前
LeetCode 1128.等价多米诺骨牌对的数量
算法·leetcode·职场和发展
ᐇ9593 小时前
Java HashMap深度解析:数据结构、原理与实战指南
java·开发语言·数据结构
十八岁讨厌编程4 小时前
【算法训练营 · 补充】LeetCode Hot100(中)
算法·leetcode
橘颂TA4 小时前
【剑斩OFFER】算法的暴力美学——最小覆盖字串
算法·c/c++·就业
wearegogog1234 小时前
基于混合蛙跳算法和漏桶算法的无线传感器网络拥塞控制与分簇新方法
网络·算法
Tiandaren5 小时前
大模型应用03 || 函数调用 Function Calling || 概念、思想、流程
人工智能·算法·microsoft·数据分析
2301_795167205 小时前
玩转Rust高级应用 如何进行理解Refutability(可反驳性): 模式是否会匹配失效
开发语言·算法·rust
小当家.1055 小时前
[LeetCode]Hot100系列.贪心总结+思想总结
算法·leetcode·职场和发展