【滑动窗口法解决子数组,子串问题】

前言

在leetCode题解中看到一位大佬针对滑动窗口法解决子数组,子串问题的总结,觉得总结的非常好,成功地将滑动窗口法变成了默写题,在这里学习记录一下。
适用于
76.最小覆盖子串
567.字符串的排列
438.找到字符串中所有字母异位词
3.无重复字符的最长子串
等题目


滑动窗口法

框架:

void slidingWindow(string s, string t) {unordered_map<char, int> need, window;for (char c : t) need[c]++;int left = 0, right = 0;int valid = 0; while (right < s.size()) {// c 是将移入窗口的字符char c = s[right];// 右移窗口right++;// 进行窗口内数据的一系列更新.../*** debug 输出的位置 ***/printf("window: [%d, %d)\n", left, right);/********************/// 判断左侧窗口是否要收缩while (window needs shrink) {// d 是将移出窗口的字符char d = s[left];// 左移窗口left++;// 进行窗口内数据的一系列更新...}}
}

其中两处 … 表示的更新窗口数据的地方,到时候你直接往里面填就行了。
而且,这两个 … 处的操作分别是右移和左移窗口更新操作,等会你会发现它们操作是完全对称的。
拿LeetCode 76 题最小覆盖子串举例子
在这里插入图片描述
滑动窗口算法的思路是这样:

  1. 我们在字符串 S 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引左闭右开区间 [left, right)
  2. 称为一个「窗口」。 我们先不断地增加 right 指针扩大窗口 [left, right),直到窗口中的字符串符合要求(包含了 T 中的所有字符)。
  3. 此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 [left, right),直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。
  4. 重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。

这个思路其实也不难,第 2 步相当于在寻找一个「可行解」,然后第 3 步在优化这个「可行解」,最终找到最优解,也就是最短的覆盖子串。左右指针轮流前进,窗口大小增增减减,窗口不断向右滑动,这就是「滑动窗口」这个名字的来历。
needs 和 window 相当于计数器,分别记录 T 中字符出现次数和「窗口」中的相应字符的出现次数。
首先,初始化 window 和 need 两个哈希表,记录窗口中的字符和需要凑齐的字符:

unordered_map<char, int> need, window;
for (char c : t) need[c]++;

然后,使用 left 和 right 变量初始化窗口的两端,不要忘了,区间 [left, right) 是左闭右开的,所以初始情况下窗口没有包含任何元素:

int left = 0, right = 0;
int valid = 0; 
while (right < s.size()) {// 开始滑动
}

其中 valid 变量表示窗口中满足 need 条件的字符个数,如果 valid 和 need.size 的大小相同,则说明窗口已满足条件,已经完全覆盖了串 T。

现在开始套模板,只需要思考以下四个问题:

  1. 当移动 right 扩大窗口,即加入字符时,应该更新哪些数据?
  2. 什么条件下,窗口应该暂停扩大,开始移动 left 缩小窗口?
  3. 当移动 left 缩小窗口,即移出字符时,应该更新哪些数据?
  4. 我们要的结果应该在扩大窗口时还是缩小窗口时进行更新?

如果一个字符进入窗口,应该增加 window 计数器;如果一个字符将移出窗口的时候,应该减少 window 计数器;当 valid 满足 need 时应该收缩窗口;应该在收缩窗口的时候更新最终结果。
下面是完整代码:

string minWindow(string s, string t) {unordered_map<char, int> need, window;for (char c : t) need[c]++;int left = 0, right = 0;int valid = 0;// 记录最小覆盖子串的起始索引及长度int start = 0, len = INT_MAX;while (right < s.size()) {// c 是将移入窗口的字符char c = s[right];// 右移窗口right++;// 进行窗口内数据的一系列更新if (need.count(c)) {window[c]++;if (window[c] == need[c])valid++;}// 判断左侧窗口是否要收缩while (valid == need.size()) {// 在这里更新最小覆盖子串if (right - left < len) {start = left;len = right - left;}// d 是将移出窗口的字符char d = s[left];// 左移窗口left++;// 进行窗口内数据的一系列更新if (need.count(d)) {if (window[d] == need[d])valid--;window[d]--;}                    }}// 返回最小覆盖子串return len == INT_MAX ?"" : s.substr(start, len);
}

438.找到字符串中所有字母异位词

class Solution {
public:vector<int> findAnagrams(string s, string p) {// needs 和 window 相当于计数器,分别记录T中字符出现次数和窗口中的相应字符的出现次数unordered_map<char,int> need, window;for(char c : p) need[c]++;int left = 0, right = 0;int valid = 0;vector<int> res;while(right < s.size()) {char c = s[right];  // c是将移入窗口的字符right++;    // 右移窗口// 进行窗口内数据的一系列更新if(need.count(c)) {window[c]++;if(window[c] == need[c]) {valid++;}}// 判断左侧窗口是否要收缩while((right - left) >= p.size()) {// 当窗口符合条件时,把起始索引加入resif(valid == need.size()) {res.push_back(left);}char d = s[left];   // d是将移出窗口的字符left++; //左移窗口// 进行窗口内数据的一系列更新if(need.count(d)) {if(window[d] == need[d]) {valid--;}window[d]--;}}}return res;}
};

参考

leetCode题解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/412334.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF- vs中的WPF应用项目模板 如何自己实现

读书笔记 1. 单个 c#文件的 空白window应用程序 (只展示了一个button按钮) 2.C#文件 和xml文件 的空白window程序 .xml文件作为程序的资源 (只一个button按钮) 3. xmal和c#共同编译 形如使用VS 创建WPF应用项目模板 1.新建一个wpf空白项目 ,添加一个主c#文件 和xaml文件(属…

手算神经网络MAC和FLOP

在本文中&#xff0c;我们将深入探讨神经网络背景下的 MAC&#xff08;乘法累加运算&#xff09;和 FLOP&#xff08;浮点运算&#xff09;概念。通过学习如何使用笔和纸手动计算这些内容&#xff0c;你将对各种网络结构的计算复杂性和效率有基本的了解。 这是 colab 笔记本中…

Java语言程序设计基础篇_编程练习题*17.13 (带GUI的组合文件工具)

目录 题目&#xff1a;*17.13 (带GUI的组合文件工具) 代码示例 结果展示 题目&#xff1a;*17.13 (带GUI的组合文件工具) 改写编程练习题17.12使之带有GUI&#xff0c;如图1721b所示 可以使用编程练习题17.11的GUI代码和编程练习题17.12的程序代码&#xff1a; Java语言…

linux系统使用 docker 来部署运行 mysql5.7 并配置 docker-compose-mysql.yml 文件

Docker是一个开源的容器化平台&#xff0c;旨在简化应用程序的创建、部署和管理。它基于OS-level虚拟化技术&#xff0c;通过将应用程序和其依赖项打包到一个称为容器的标准化单元中&#xff0c;使得应用程序可以在任何环境中快速、可靠地运行。 Docker的优势有以下几个方面&a…

SpringMVC 笔记篇

1.1 执行流程 1.1.5 DispatcherServlet的init()——> 创建Spring容器 ——> initStrategies()方法 在1.1.4中DispatcherServlet中的init()方法创建Spring容器之外&#xff0c;其实还会做一件特别重要的事&#xff0c;在FrameworkServlet中的refresh()方法执行之前&…

景联文科技提供运动数据采集服务

运动数据的重要性 运动数据的收集与分析对于提升个人健康管理和运动表现具有重要意义。 通过收集心率、步态、速度等生理和运动参数&#xff0c;不仅可以为运动员提供个性化的训练方案&#xff0c;帮助其优化表现&#xff0c;还能早期发现并预防伤病。对于普通健身者而言&…

CSS溢出——WEB开发系列20

在网页设计中&#xff0c;“溢出”是一个常见且重要的概念。它涉及到如何处理那些超出预定范围的内容&#xff0c;以确保网页的布局和视觉效果达到预期。 一、什么是溢出&#xff1f; 在 CSS 中&#xff0c;“溢出”&#xff08;overflow&#xff09;指的是内容超出其包含块的…

python-pptx - Python 操作 PPT 幻灯片

文章目录 一、关于 python-pptx设计哲学功能支持 二、安装三、入门1、你好世界&#xff01;例子2、Bullet 幻灯片示例3、add_textbox()示例4、add_picture()示例5、add_shape()示例6、add_table()示例7、从演示文稿中的幻灯片中提取所有文本 四、使用演示文稿1、打开演示文稿2、…

Marscode:程序员的智能伙伴,2024 活动震撼来袭

在程序员的世界里&#xff0c;高效的开发工具如同手中的利器&#xff0c;能让我们在代码的海洋中披荆斩棘。今天&#xff0c;我要向大家隆重介绍一款强大的智能开发工具——Marscode&#xff0c;以及它带来的精彩 2024 活动。 一、Marscode&#xff1a;智能开发的新势力 Mars…

SQLite的安装和使用

一、官网链接下载安装包 点击跳转 步骤&#xff1a;点击安装这个红框的dll以及红框下面的tools &#xff08;如果有navicat可以免上面这个安装步骤&#xff0c;安装上面这个是为了能在命令行敲SQL而已&#xff09; 二、SQLite的特点 嵌入的&#xff08;无服务器的&#x…

【机器学习】 7. 梯度下降法,随机梯度下降法SGD,Mini-batch SGD

梯度下降法,随机梯度下降法SGD,Mini-batch SGD 梯度下降法凸函数(convex)和非凸函数梯度更新方向选择步长的选择 随机梯度下降SGD(Stochastic Gradient Descent)梯度下降法&#xff1a;SGD: Mini-batch SGD 梯度下降法 从一个随机点开始决定下降方向&#xff08;重要&#xff…

基于PHP+MySQL组合开发的微信投票小程序 带完整的安装代码包以及搭建教程

系统概述 这款基于 PHPMySQL 组合开发的微信投票小程序是一款专门为满足各类投票需求而设计的应用程序。它利用 PHP 强大的服务器端编程能力和 MySQL 高效的数据存储和管理能力&#xff0c;为用户提供了一个稳定、可靠、功能丰富的投票平台。 该小程序支持多种投票类型&#…

centos安装docker并配置加速器

docker安装与卸载&#xff1a; 1、检查当前是否安装docker yum list installed | grep docker2、卸载docker 根据yum list installed | grep docker查询出来的内容&#xff0c;逐个进行删除 yum remove docker.x86 64 -y3、启动与关闭docker 4、删除/etc/docker文件夹 如果…

jmeter 响应乱码

Jmeter在做接口测试的时候的&#xff0c;如果接口响应的内容中有中文&#xff0c;jmeter的响应内容很可能显示乱码&#xff0c;为了规避这种出现乱码的问题&#xff0c;就要对jmeter的响应结果进行编码处理。 打开jmeter进行接口、压力、性能等测试&#xff0c;出现以下乱码问…

Java短剧系统新生态智能系统打造个性化影视体验小程序源码

短剧新生态&#xff0c;智能系统打造个性化影视体验✨&#x1f3ac; &#x1f389; 开篇&#xff1a;短剧新纪元&#xff0c;个性化体验来袭 在这个快节奏的时代&#xff0c;短剧以其精炼的剧情和高效的传播力&#xff0c;正逐渐成为影视娱乐的新宠儿&#xff01;&#x1f38…

如何恢复删除的微信好友?不留遗憾,这5招教你找回

在社交生活中&#xff0c;微信成为了我们日常沟通的重要工具之一。然而&#xff0c;偶尔因一时冲动或误操作删除了重要好友&#xff0c;当我们想找回好友时是否也在懊悔呢&#xff1f;如何恢复删除的微信好友就成为了我们必须学会的技能。那么&#xff0c;今天我们就来分享5种高…

10、ollama启动LLama_Factory微调大模型(llama.cpp)

在前面章节中介绍了如何使用LLama_Factory微调大模型&#xff0c;并将微调后的模型文件合并导出&#xff0c;本节我们我们看下如何使用ollama进行调用。 1、llama.cpp LLama_Factory训练好的模型&#xff0c;ollama不能直接使用&#xff0c;需要转换一下格式&#xff0c;我们…

STM32G474之TIM1更新中断

STM32G474之TIM1能产生如下的中断&#xff1a; 1、捕获比较1个事件&#xff08;Capture compare 1 event&#xff09; 用来获取“捕获输入脉冲的时间”&#xff0c;其次用来输出“比较输出波形”&#xff1b; 2、捕获比较2个事件&#xff08;Capture compare 2 event&#x…

【HTML源码】上传即可使用的在线叫号系统源码

这个叫号系统的过程是这样的 接了一个任务&#xff0c;某学校要对学生进行逐个面试&#xff0c;希望能有类似医院门诊那种叫号系统。 条件&#xff1a;首先说硬件&#xff0c;就是教室里边一台笔记本电脑&#xff0c;同屏到教室外面的电视机。 需求&#xff1a;软件需求是可…

如何解决U盘无法压缩卷或删除卷的问题

U盘在日常使用中&#xff0c;偶尔会遇到无法压缩卷或删除卷的情况。出现这些问题通常与U盘的磁盘状态或文件系统有关。本文将介绍一种有效的解决方法&#xff0c;通过使用Windows自带的磁盘管理工具diskpart来解决这些问题。 一、问题原因 U盘无法压缩卷或删除卷的常见原因包…