滑动窗口

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

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 ,并返回其长度。如果不存符合条件的子数组,返回0。

 

示例 :

输入:target = 7, nums = [2,3,1,2,4,3]

输出:2

解释:子数组 [4,3] 是该条件下的长度最小的子数组。

 

1、三层循环:

for (i=0;i<=len-1;i++) #起始位置
       for(j=1;j<=len-1-i+1;j++) #取的长度
             for(k=i;k<=i+j-1;k++) #终止位置

2、两层循环:

for(i=0;i<=len-1;i++){     #起始位置
            ans=0;
            for(j=i;j<=len-1;j++){   #终止位置。相比于三层循环优化在于:累加便可算出起始位置到终止位置的和。无需多一层循环
                ans+=nums[j];
                if(ans>=target){
                    length=min(length,j-i+1);
                }
            }
        }

3、滑动窗口:

我的代码:不太清晰,但写了几次都是这个。当我们的值达到了目标值就开始从起始位置减,重复这个过程。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int len=nums.size();
        int i,j,k;
        int ans=len;
        int ans1=0;
        int sum=0;
        for(j=0;j<=len-1;j++){
            ans1+=nums[j];
        }
        if(ans1<target){
            return 0;
        }
        for(i=0,j=0;j<=len-1;){
            while(sum<target&&j<=len-1){
                
                sum+=nums[j++];
            }
            while(sum>=target){
                ans=min(ans,j-1-i+1);
                sum-=nums[i++];
            }
        }
        return ans;
    }
};

更为标准的代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int len=nums.size();
        int i,j,k;
        int ans=0x3f3f3f3f;
        int ans1=0;
        int sum=0;
        i=0;
        for(j=0;j<=len-1;j++){
            sum+=nums[j];
            while(sum>=target){
                ans=min(ans,j-i+1);
                sum-=nums[i++];
            }
        }
        return ans==0x3f3f3f3f?0:ans;
    }
};

 

时间复杂度:O(n)

空间复杂度:O(1)

为什么时间复杂度是O(n)?

不要以为for里放一个while就以为是O(n^2), 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。

代码随想录真的贴心。

 

滑动窗口的要点:

1、明确有一个窗口开始端S,一个窗口终止端e。e是循环控制不断向后的,S是在当前情况满足题目条件后不断更新寻找最优。

滑动窗口的S端何时往后移动是一个比较关键的点。

posted @ 2023-11-17 20:48  我的秘密小屋  阅读(3)  评论(0编辑  收藏  举报