滑动窗口——优选算法

个人主页:敲上瘾-CSDN博客

个人专栏:游戏数据结构c语言基础c++学习算法

目录

一.滑动窗口算法原理:

二.无重复字符的最长子串

1.题目解析​编辑

2.算法原理

3.代码编写

三.长度最小的子数组

1.题目解析

2.算法原理

3.代码编写

四.最小覆盖子串

1.题目解析

2.算法原理

3.代码编写

五.总结


一.滑动窗口算法原理:

滑动窗口可以说是一种特殊双指针算法,即它同样用两个指针实现。**滑动窗口:用一个left指针和right指针来维护一段区间即[left, right],也可称为窗口,right右移即进窗口,left右移即出窗口。**即通常情况下left和right指针都是同向移动的。对于滑动窗口我们主要关心以下几点:

++进窗口,出窗口,更新结果。进窗口肯定是在出窗口前进行的,而什么时候更新结果因题而异。++

其实对于滑动窗口本身还是挺简单的,难点在我们能不能想到使用滑动窗口,接下来我准备了三个题,每题都分为三个步骤:题目解析,算法原理,代码编写。从最普通的暴力解法过渡到滑动窗口。最后来做总结。

二.无重复字符的最长子串

1.题目解析

该题需要我们求出字符串s内无重复字符的最长子串,注意这里子串的意思也就是在字符串s内连续的一段字符,所以在求解该题时最好不要对原字符串进行改动。

2.算法原理

明显这道题很容易想到的就是暴力枚举,但是时间复杂度比较高是过不了该题的测试的。在我们没能想到其他解法时,可以这样做,去分析暴力解法,从暴力解法中找到优化的规律。如下:

按以上方法把整个数组遍历完可以解决这个题目,但可以做以下优化:

这就是一个滑动窗口,把[left, right]区间当作一个窗口存放的是不重复的子串,然后用一个len变量来记录窗口的最大长度,当right滑动到字符串结尾时也就把所有的情况都记录了一遍,此时结束循环返回len该算法就完成了。

注意:这里因为要检查字符是否重复所以用一个哈希表来记录窗口内数据出现的个数可以提高效率。

3.代码编写

cpp 复制代码
class Solution 
{
public:
    int lengthOfLongestSubstring(string s) 
    {
        if(s.size()==0) return 0;
        int len=-1;
        int arr[127]={0};
        for(int left=0,right=0;right<s.size();right++)
        {
            arr[s[right]]++;
            cout<<arr[s[right]]<<' ';
            while(arr[s[right]]==2)
            {
                arr[s[left++]]--;
            }
            if(len<right-left+1) len=right-left+1;
        }
        return len;
    }
};

三.长度最小的子数组

1.题目解析

本题要求子数组(即数组内的一段连续的元素)的元素之和大于等于target的最小长度,如果不存在返回0。例如示例1,[2,3,1,2,4,3]中子数组大于等于target的子数组有:

2,3,1,2\],\[2,3,1,2,4\],\[2,3,1,2,4,3\],\[3,1,2,4\], \[3,2,1,4,3\],\[1,2,4\],\[1,2,4,3\],\[2,4,3\],\[4,3\]。 而长度最小的子数组为\[4,3\],长度为2,以上所列的子数组是一个模拟暴力枚举的结果。 ### 2.算法原理 该题可以使用暴力枚举(即两个循环解决)时间复杂度为O(N\^2)。对于暴力解法在这里就不再多讲,现在我们可以试图从暴力解法中寻找规律并进行优化。如下: ![](https://i-blog.csdnimg.cn/direct/c4f1640a571f46d9ab28654690a3fe8e.png) 以上我们分析的结果就是一个滑动窗口算法,left,right来维护这个窗口,left右移即出窗口,right右移即进窗口,当窗口里的元素之和大于等于target时更新最小长度。直到right滑动到数组结尾可得到答案。时间复杂度为O(N)。 ### 3.代码编写 ```cpp class Solution { public: int minSubArrayLen(int target, vector& nums) { int left=0,right=0; int sum=0,len=0; while(right=target) { int ln=right-left+1;//计算窗口长度 if(len==0||len>ln) len=ln;//更新len sum-=nums[left++];//出窗口 } right++; } return len; } }; ``` ## 四.最小覆盖子串 ### 1.题目解析 ![](https://i-blog.csdnimg.cn/direct/faefb37c09f84c99ad79755c959cab7c.png) 题目意思是给一个字符串s和t,要求在字符串s中找一个子串,这个子串要满足两点:(1)涵盖t字符串里的所有字符(包括重复字符),(2)最短的一个子串。注意:这个子串的要求不是涵盖t字符串,而是涵盖t字符串中的所有字符,这两者是有区别的。如示例1到3。 ### 2.算法原理 同样这题也是可以使用暴力枚举的,我们还是从暴力枚举中去寻找规律并优化。 ![](https://i-blog.csdnimg.cn/direct/883d93469c6e4ce3ae6e46036963f554.png) 分析到此处,我们可以发现解题思路和上题可以说几乎是一模一样,但该题真正的难点并不是在此处。而在于我们如何去判断子串中是否包含t中的所有字符。 因为这里对子串中t的字符并没每有顺序要求,只要个数对上就行了,所以我们很自然地可以想到使用哈希表(此题使用数组充当哈希表更为高效)来记录数据出现个数。具体怎么判断呢? 使用两个哈希表分别记录t中的字符以及个数和子串(窗口)中字符以及出现个数。然后使用遍历的方式去匹配并判断。这样确实行得通,不过涉及遍历时间复杂度一下子就上来了。在这里我给大家分享一个小技巧,是官方题解上没有的。同样我们用这两个哈希表,但不用遍历去匹配判断,而是使用一个count变量记录子串(窗口)中有效字符的个数, 进窗口:当子串中某字符的个数与t字符串中对应字符个数相等时(用哈希表判断),有效字符count++。 更新结果并出窗口:当count等于t中的字符种类数时,判断并更新结果,当出窗口的元素为有效元素时(哈希表判断)count--。 ### 3.代码编写 ```cpp class Solution { public: string minWindow(string s, string t) { string str;//储存最终结果 if(s.size()

相关推荐
予安灵1 分钟前
第十二届蓝桥杯省赛软件类(c&c++组)
c语言·c++·蓝桥杯
chen_song_4 分钟前
WebRTC的ICE之TURN协议的交互流程中继转发Relay媒体数据的turnserver的测试
算法·音视频·webrtc·交互·媒体
蒙奇D索大20 分钟前
【数据结构】图解图论:度、路径、连通性,五大概念一网打尽
数据结构·考研·算法·图论·改行学it
uhakadotcom24 分钟前
2025年春招:如何使用DeepSeek + 豆包优化简历,轻松敲开心仪公司的大门
算法·面试·github
小白狮ww28 分钟前
Retinex 算法 + MATLAB 软件,高效率完成图像去雾处理
开发语言·人工智能·算法·matlab·自然语言处理·图像识别·去雾处理
444A4E1 小时前
C++模板:泛型编程的魔法手册,从入门到“魔改”
c++·编译原理
TGITCIC1 小时前
BERT与Transformer到底选哪个-下部
人工智能·gpt·大模型·aigc·bert·transformer
trust Tomorrow2 小时前
每日一题-力扣-2278. 字母在字符串中的百分比 0331
算法·leetcode
Chiyamin2 小时前
C++面向对象速览(三)
c++
Tadecanlan2 小时前
[C++面试] 智能指针面试点(重点)续4
开发语言·c++·面试