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

相关推荐
nudt_qxx20 小时前
CUDA编程模型与硬件执行层级对应关系
linux·人工智能·算法
m0_5312371721 小时前
C语言-分支与循环语句练习2
c语言·开发语言·算法
AIpanda88821 小时前
什么是AI销冠系统和AI提效软件系统?主要区别和应用场景是什么?
算法
程序员酥皮蛋21 小时前
hot 100 第三十三 33.排序链表
数据结构·算法·链表
蚊子码农21 小时前
算法题解记录-2452距离字典两次编辑以内的单词
开发语言·算法·c#
重生之后端学习21 小时前
207. 课程表
java·数据结构·算法·职场和发展·深度优先
Tisfy1 天前
LeetCode 1523.在区间范围内统计奇数数目:两种方法O(1)算
算法·leetcode·题解
癫狂的兔子1 天前
【Python】【机器学习】线性回归
算法·回归·线性回归
野犬寒鸦1 天前
ArrayList扩容机制深度解析(附时序图详细讲解)
java·服务器·数据结构·数据库·windows·后端
tankeven1 天前
HJ92 在字符串中找出连续最长的数字串
c++·算法