坐牢之“滑动窗口”

滑动窗口是一种高效解决数组或字符串中子区间问题的技巧 

我觉得较为经典的滑窗的背景问题是:

1456. 定长子串中元音的最大数目

算术评级: 4第 190 场周赛Q2

给你字符串 s 和整数 k 。

请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。

英文中的 元音字母 为(aeiou

在这个题目背景下,我们首先要明确“子字符串”(连续的字符集)“子序列”(保持原有顺序关系的不要求连续的字符集)的区别

这类题目背景下,有两个变量(哪个子字符串)(对应的元音字母数

我们记为x和y,那么这就是数学中的函数关系——“x是自变量,y是同时变的因变量”,在这样的情况下,时间复杂度就降为一次循环O(n)(原来的时间复杂度是 O(nk))

其实我们注意到,这个窗口是一个定长的,因此每次窗口移动“进入”和“退出”的字符数相同并且一头一尾——————那么我们循环时每次考虑(入-更新数-出

class Solution {
public:
    int maxVowels(string s, int k) {
        int ans = 0, vowel = 0;
        for (int i = 0; i < s.length(); i++) {
            // 1. 进入窗口
            if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') {
                vowel++;
            }
            if (i < k - 1) { // 窗口大小不足 k
                continue;
            }
            // 2. 更新答案
            ans = max(ans, vowel);
            // 3. 离开窗口
            char out = s[i - k + 1];
            if (out == 'a' || out == 'e' || out == 'i' || out == 'o' || out == 'u') {
                vowel--;
            }
        }
        return ans;
    }
};

 进阶——不定长滑窗

上面说了定长滑窗,理所当然的就有不定长的,其实这就是本系列上一篇“双指针”中的两个指针状态决定的,两个指针是同速还是不同速?是相向还是相对?

不定长滑窗的情况一般是异速同向类别的。

基本步骤就和上面的定长滑窗示例代码类似:

  1. 初始化:定义窗口的左右边界 leftright,通常从数组或字符串的起点开始。
  2. 扩展窗口:移动 right(右边界),将新元素加入窗口。
  3. 收缩窗口:当窗口满足特定条件时,尝试移动 left(左边界)以缩小窗口。
  4. 更新结果:在满足条件时,记录当前窗口的解,并根据需要进行更新。
  5. 重复步骤 2-4,直到右边界遍历完整个数组或字符串。

常见问题类型(没啥意义)

1. 最小窗口问题

描述:在一个字符串或数组中,找到满足特定条件的最小长度子区间。

例子:在字符串 s 中找到包含 t 中所有字符的最小窗口。


2. 最大窗口问题

描述:在数组中找到满足特定条件的最大长度子区间。

例子:在一个数组中,找到最多包含两个不同元素的最长连续子数组。


3. 子数组和问题

描述:找到数组中和大于等于目标值的最短子数组。

例子:在数组中找到和大于等于 target 的最短子数组。


4. 无重复子字符串问题

描述:找到字符串中无重复字符的最长子串。


推荐引流

这个就不给代码了,其实和上面的代码类似的,我还是实际点,本来就是“卷帙浩繁”的一个技巧了,到处都是解析的文章,我不献丑了,给出灵神的相关题单:

分享丨【题单】滑动窗口与双指针(定长/不定长/至多/至少/恰好/单序列/双序列/三指针) - 力扣(LeetCode)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值