leetcode209.长度最小的子数组

目录

    • 一、算法分析
      • (1)思路——滑动窗口
      • (2)时间复杂度
    • 二、参考代码

leetcode209题目直达

一、算法分析

(1)思路——滑动窗口

  1. 我们在数组nums 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引区间 [left, right] 称为一个「窗口」。
  2. left不动,不断地增加 right 指针扩大窗口,直到窗口符合要求(窗口内数值之和>=target)。
  3. 此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 ,直到窗口不再符合要求。
  4. 重复第 2 和第 3 步,直到 right 到达数组末尾。

(: 第 2 步相当于在寻找一个「可行解」,然后第 3 步在优化这个「可行解」,最终找到最优解,也就是最短的覆盖子串。左右指针轮流前进,窗口大小增增减减,窗口不断向右滑动,这就是「滑动窗口」。)

这里参考:labuladong大佬的算法小抄

(2)时间复杂度

该算法的时间复杂度是O(n)。

不要见到两个循环嵌套就以为时间复杂度是O(n^2),
时间复杂度主要是看每一个元素被操作的次数,每个元素在滑动窗口往右扩大时进来一次,窗口缩小时出去一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。

二、参考代码

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int numsSize = nums.size();
        if (numsSize == 0) return 0;//判断数组是否为空
        int resMin = INT_MAX;
        /*
        resMin表示最终取的符合条件的最短的子数组长度.
        INT_MAX是C++中的常量,表示int型的最大值,包含在头文件limits.h中.
        这样才能不断更新取所有窗口长度的最小值
        */
        int left = 0, right = 0;
        //左右指针,滑动窗口的左右两端
        int sum = 0, subLen = 0; 
        //窗口数值之和, 窗口的长度
        while (right < numsSize) {
            //left不变,right右移扩大窗口,直到满足要求进入下面的while循环
            sum += nums[right];
            //满足要求之后left右移缩小窗口优化这个解,直到不满足要求
            while (sum >= target) {
                subLen = right - left + 1;
                //先计算出当前滑动窗口的长度
                //再和resMin作比较,若sublen更小则更新resMin
                resMin = subLen < resMin ? subLen : resMin;
                //也可以写成resMin = min(subLen, resMin);
                sum -= nums[left++];
            }
            right++;
            //若此时窗口不满足要求(不会进入while循环)则right++扩大窗口
            //若满足要求找到一个优化解之后right右移继续往后找更多解
        }
        return resMin == INT_MAX ? 0 : resMin;
        //若resMin未改变说明数组中不存在符合条件的子数组
    }
};

你可能感兴趣的:(算法题解,c++,算法,leetcode)