【代码随想录刷题记录】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。

相关推荐
那个村的李富贵2 小时前
CANN加速下的AIGC“即时翻译”:AI语音克隆与实时变声实战
人工智能·算法·aigc·cann
power 雀儿2 小时前
Scaled Dot-Product Attention 分数计算 C++
算法
Yvonne爱编码2 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
熬夜有啥好2 小时前
数据结构——哈希表
数据结构·散列表
琹箐2 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
renhongxia13 小时前
如何基于知识图谱进行故障原因、事故原因推理,需要用到哪些算法
人工智能·深度学习·算法·机器学习·自然语言处理·transformer·知识图谱
坚持就完事了3 小时前
数据结构之树(Java实现)
java·算法
算法备案代理3 小时前
大模型备案与算法备案,企业该如何选择?
人工智能·算法·大模型·算法备案
赛姐在努力.3 小时前
【拓扑排序】-- 算法原理讲解,及实现拓扑排序,附赠热门例题
java·算法·图论
我能坚持多久4 小时前
【初阶数据结构01】——顺序表专题
数据结构