自学内容网 自学内容网

长度最小的子数组(滑动窗口)

209. 长度最小的子数组 - 力扣(LeetCode)

题目描述

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的子数组[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

示例

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组[4,3]是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

题解

先给出滑动窗口的模板代码

for(扩展右边界){
    while(condition){
        更新区间
        缩小左边界
    }
}

其中,扩展右区间的过程就是遍历数组的过程 

滑动窗口的思想:

  • 定义两个指针 start 和 end 分别表示子数组(滑动窗口窗口)的开始位置和结束位置
  • 维护满足题意的区间条件并更新区间

文字不好描述,我们直接看这道题

  • 首先我们使用两个指针固定一个区间,并计算这个区间的数值和
  • 判断区间和是否大于等于target,如果不满足这个题意条件,就扩展右区间
  • 假如我们找到了一个满足题意的区间[left,right],此时就记录并更新区间长度
  • 此时就不能再继续扩展右边界了,因为题目要求的是找最小的区间长度,再继续扩展显然区间长度会变大,因此就尝试缩小左边界
  • 缩小左边界时会遇到两种情况
    • 缩小后的区间[left0,right](其中left0表示缩小后的边界值),仍旧满足题意,则更新区间长度,同时继续尝试缩小左侧边界
    • 缩小后的区间[left0,right](其中left0表示缩小后的边界值),不满足题意,则不能再缩小左侧边界,此时的区间已经不满足题意,那么再缩小显然也不满足题意,于是继续扩展右边界

手动模拟过程如下所示 

代码模拟如下

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //定义左边界
        int i=0;
        //定义结果变量
        int res=INT_MAX;
        //用于计算子区间的和
        int sum=0;
        //不断扩展右边界,相当于在遍历数组
        for(int j=0;j<nums.size();++j){
            //右边界在遍历数组的过程中计算区间和
            sum+=nums[j];
            //当满足题意时,就记录并更新子区间的长度,同时缩小左边界
            while(sum>=target){
                res=min(res,j-i+1);
                //更新区间和,并缩小左边界
                sum-=nums[i++];
            }
        }
        return (res==INT_MAX)?0:res;
    }
};

 其中

 sum-=nums[i++];

这段代码相当于

sunm-=nums[i];
i++;

 因为缩短左边界的同时还要保存区间长度和sum


原文地址:https://blog.csdn.net/qq_58158950/article/details/143605014

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!