题目地址

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),其具体代码实现如下(顺利通过):

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。

05-01 10:12