2021-09-17 209. 长度最小的子数组(滑动窗口)

注:

题目:
给定一个含有 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

提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105

进阶:
如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

题解:
解题思路
连着做了好几道滑动窗口的题目,实现滑动窗口的框架是定死的,用left,right来刻画窗口,窗口区间为[left, right),注意为半开半闭。框架如下:

void slidwindow(vector<int> nums)
{
    int left = 0, right = 0;
    while(right < nums.size())
    {
        ...//扩大右边界并更新窗口状态
        right++;
        while(需要收缩)//窗口到达什么状态需要收缩
        {
            ...//缩小左边界并更新窗口状态
            left++;
        }
    }
}

滑动窗口重点在于:

  • 需要关注窗口的状态是什么?
  • 需要如何刻画当前窗口的状态?
  • 窗口到达什么状态时需要收缩?

显然对于这道题,我们需要关注的窗口状态就是窗口内所有数的和,那么如何刻画窗口状态呢?我们设置了一个变量sum,显然这个变量需要在窗口边界发生改变时不断更新,框架注释已经给出。

那么窗口到达什么状态需要收缩呢?即内部while循环的条件,显然当窗口内部所有数字的和>=target我们就收缩来寻找更小的满足条件的窗口。这样一来代码就很好写了。

复杂度分析
时间复杂度:O(n),其中 n 是数组的长度。指针 start 和 end 最多各移动 n 次。
间复杂度:O(1)。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int start=0;
        int end=0;
        int sum=0;
        int lens=INT_MAX;
        int size=nums.size();
        while(end<size){
            sum+=nums[end];
            end++;
            while(sum>=target){
                lens=min(lens,end-start);
                sum-=nums[start];
                start++;
            }
        }
        return lens==INT_MAX?0:lens;
    }
};

你可能感兴趣的:(leetcode,算法,滑动窗口)