算法中的移动窗帘——C++滑动窗口算法详解

1. 滑动窗口简介

滑动窗口是一种在算法中常用的技巧,主要用来处理具有连续性的子数组或子序列问题。通过滑动窗口,可以在一维数组或字符串上维护一个固定或可变长度的窗口,逐步移动窗口,避免重复计算,从而提升效率。常用于求解子数组的最大/最小值、满足条件的子数组个数等问题。

滑动窗口的两种类型

1. 固定大小的滑动窗口:窗口大小固定不变,通常适合于问题中要求找定长子数组的最大值、最小值等情况。
2. 可变大小的滑动窗口:窗口大小根据条件动态调整,通常适用于子数组和达到一定值或满足特定条件的情况。

滑动窗口的实现步骤

以可变大小的滑动窗口为例,一般步骤如下:

1. 初始化窗口的左右边界(例如 `left` 和 `right` 指针),并根据问题需求定义窗口内需要维护的变量(如窗口内的和、计数等)。
2. 移动右边界 `right`,将新元素加入窗口,并更新窗口内的变量。
3. 检查当前窗口是否满足条件。如果满足,记录答案(如更新最大/最小值),然后移动左边界 `left` 以缩小窗口,继续寻找其他符合条件的窗口。
4. 重复步骤 2 和 3,直到右边界遍历完数组。

应用场景

滑动窗口常用于以下几类问题:
- 子数组和问题(如最大、最小和)
- 子字符串问题(如最长无重复子串)
- 符合条件的区间统计

这种方法在处理需要频繁访问连续子序列的问题时具有高效性。

2. 长度最小的子数组

一、题目介绍

二、思路解析

方法一:暴力枚举

 枚举 将数组中的每个元素 都当做起点,向后遍历数组寻找最短区间,最后找到将所有元素当做期待所得结果的最小值。

优化方法:滑动窗口 :

由于此问题分析的对象是「⼀段连续的区间」,因此可以考虑「滑动窗口」的思想来解决这道题。

(1)left = 0, right = 0

(2)进窗口

- 当窗口中的值小于target是,进窗口

(3)判断什么时候出窗口并更新结果

- 当窗口中的值大于等于target时,窗口中的值减去left位置的值(更新结果),出窗口(left++)

三、代码实现

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size(), sum = 0, len = INT_MAX;
        for (int left = 0, right = 0; right < n; right++)
        {
            sum += nums[right];//进窗口
            while (sum >= target) // 判断
            {
                len = min(len, right - left + 1); // 更新结果
                sum -= nums[left++]; // 出窗口
            }
        }
        return len == INT_MAX ? 0 : len;
    }
};

. - 力扣(LeetCode)

为何滑动窗口可以解决问题,并且时间复杂度更低?
- 这个窗口寻找的是:以当前窗口最左侧元素(记为 left1 )为基准,符合条件的情况。也就是在这道题中,从 left1 开始,满足区间和 sum >= target 时的最右侧(记为right1 )能到哪里。
- 我们既然已经找到从 left1 开始的最优的区间,那么就可以大胆舍去 left1 。但是如
果继续像方法一⼀样,重新开始统计第二个元素( left2 )往后的和,势必会有大量重复
的计算
- 此时, rigth1 的作用就体现出来了,我们只需将 left1 这个值从 sum 中剔除。从right1 这个元素开始,往后找满足  left2 元素的区间(此时 right1 也有可能是满足的,因为 left1 可能很小。 su
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值