【算法】滑动窗口—最小覆盖子串
题目
”最小覆盖子串“问题,难度为Hard,题目如下:
给你两个字符串 S 和 T,请你在 S 中找到包含 T 中全部字母的最短子串。如果 S 中没有这样一个子串,则算法返回空串,如果存在这样一个子串,则可以认为答案是唯一的。
比如输入 S = "ADBECFEBANC",T = "ABC",算法应该返回 "BANC"。
如果我们使用暴力解法,代码大概是这样的:
for (int i = 0; i < s.size; i++) {
for (int j = i + 1; j < s.size; j++) {
if [i : j] 包含 t 的所有字母:
更新答案
}
}
思路很简单,但显然不是我们想要的。
滑动窗口思路分析
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 中字符出现次数和”窗口“中的相应字符的出现次数。
初始状态:
增加 right,直到窗口 [left, right) 包含了 T 中所有字符:
现在开始增加 left,缩小窗口 [left, right):
直到窗口中的字符串不再符合要求,left 不再继续移动:
之后重复上述过程,先移动 right,再移动 left······直到 right 指针到达字符串 S 的末端,算法结束。现在来看看滑动窗口代码框架怎么用。
首先,初始化 window 和 need 两个哈希表,记录窗口中的字符和需要凑齐的字符:
Map<Character, Integer> need = new HashMap<>();
Map<Character, Integer> window = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
char key = t.charAt(i);
need.put(key, need.getOrDefault(key, 0) + 1);
}
然后,使用 left 和 right 变量初始化窗口的两端,不要忘了,区间 [left, right) 是左闭右开的,所以初始情况下窗口没有包含任何元素:
int left = 0, right = 0, valid = 0;
while (right < s.length()) { // 开始滑动 }
其中,valid 变量表示窗口中满足 need 条件的字符个数,如果 valid 和 need.size 的大小相同,则说明窗口已满足条件,已经完全覆盖了串 T。
现在开始套模板,只需要思考以下4个问题:
1.当移动 right 扩大窗口,即加入字符时,应该更新哪些数据?
2.什么条件下,窗口应该暂停扩大,开始移动 left 缩小窗口?
3.当移动 left 缩小窗口,即移出字符时,应该更新哪些数据?
4.我们要的结果应该在扩大窗口时还是缩小窗口时进行更新?
一般来说,如果一个字符进入窗口,应该增加 window 计数器;如果一个字符移出窗口,应该减少 window 计数器;当 valid 满足 need 时应该收缩窗口;收缩窗口的时候应该更新最终结果。
下面是完整代码:
package SlidingWindow;import java.util.HashMap;
import java.util.Map;// leetcode 017 最小覆盖子串
public class MCS {public String slidingWindow(String s, String t) {Map<Character, Integer> need = new HashMap<>();Map<Character, Integer> window = new HashMap<>();for (int i = 0; i < t.length(); i++) {char key = t.charAt(i);need.put(key, need.getOrDefault(key, 0) + 1);}int left = 0, right = 0, valid = 0; // valid 表示窗口中满足 need 条件的字符个数// 记录最小覆盖子串的启始索引及长度int start = 0, len = Integer.MAX_VALUE;while (right < s.length()) {// c 是将要移入窗口的字符char c = s.charAt(right);// 右移窗口right++;// 进行窗口内数据的一系列更新if (need.containsKey(c)) {window.put(c, window.getOrDefault(c, 0) + 1);if (window.getOrDefault(c, 0).equals(need.getOrDefault(c, 0))) { // window[c] == need[c]valid++;}}/*** debug 输出的位置***/System.out.println("window:(" + left + ", " + right + ")");/*********************/// 判断左侧窗口是否要收缩while (valid == need.size()) { // window need shrink —窗口需要收缩// 在这里更新最小覆盖子串if (right - left < len) {start = left;len = right - left;}// d 是将要移出窗口的字符char d = s.charAt(left);// 左移窗口left++;// 进行窗口内数据的一系列更新if (need.containsKey(d)) {if (window.getOrDefault(d, 0).equals(need.getOrDefault(d, 0))) {valid--;}window.put(d, window.getOrDefault(d, 0) - 1);}}}// 返回最小覆盖子串return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len); // s.substring(start, start + len) == C++ 中的 s.substr(start, len)}public static void main(String[] args) {MCS mcs = new MCS();String str = mcs.slidingWindow("ADOBECODEBANC", "ABC");System.out.println(str);}}
相关文章:

【算法】滑动窗口—最小覆盖子串
题目 ”最小覆盖子串“问题,难度为Hard,题目如下: 给你两个字符串 S 和 T,请你在 S 中找到包含 T 中全部字母的最短子串。如果 S 中没有这样一个子串,则算法返回空串,如果存在这样一个子串,则可…...

“Fast-forward“ in git-pull result
当你执行 git pull 并且结果显示 Fast-forward 时,这意味着你的本地分支可以直接快进到远程分支的最新提交,没有任何冲突或者需要合并的内容。具体来说,Fast-forward 是一种合并方式,它的特点是将当前分支的指针直接移动到远程分支…...

Oracle(133)如何创建表空间(Tablespace)?
在Oracle数据库中,表空间(Tablespace)是存储数据的逻辑单位,它由一个或多个数据文件组成。表空间是数据库数据管理的基本结构,了解如何创建表空间对于数据库管理员至关重要。 创建表空间的基本语法 创建表空间的基本…...

Linux中权限和指令
💥1、Linux基本指令 1.1 mv 指令 mv指令是move的缩写,用来移动或重命名文件、目录,经常用来备份文件或目录。 mv old_name new_name: 重命名文件或目录mv file /path/to/directory: 移动文件到指定目录 roothcss-ecs…...

本地镜像发布到阿里云
本地镜像发布到阿里云 登录阿里云容器镜像服务配置 Docker 登录阿里云容器镜像服务标记你的 Docker 镜像推送镜像到阿里云验证使用阿里云镜像注意事项 将 Docker 本地镜像发布到阿里云(Alibaba Cloud)容器镜像服务(Container Registry&#x…...

【Linux】【Vim】Vim 基础
Vim/Gvim 基础 文本编辑基础编辑操作符命令和位移改变文本重复改动Visual 模式移动文本(复制、粘贴)文本对象替换模式 光标移动以 word 为单位移动行首和行尾行内指定单字符移动到匹配的括号光标移动到指定行滚屏简单查找 /string标记 分屏vimdiff 文本编辑 基础编辑 Normal 模…...

计算机人工智能前沿进展-大语言模型方向-2024-09-18
计算机人工智能前沿进展-大语言模型方向-2024-09-18 1. The Application of Large Language Models in Primary Healthcare Services and the Challenges W YAN, J HU, H ZENG, M LIU, W LIANG - Chinese General Practice, 2024 人工智能大语言模型在基层医疗卫生服务中的应…...

ubuntu24安装vivado24(安装并解决若干错误)
目录 安装方法:问题1:解决办法: 问题2:解决方法: 安装完成: 安装方法: 注意:内存最好预留80G空闲的。 安装好大小: 安装依赖库: sudo apt-get update sud…...

CSS实现文本溢出省略号或完整显示
目录 前言1. 省略号2. 完整展示3. Demo 前言 文本内容超出容器宽度的问题,为了保持页面布局的整洁,通常会使用省略号来隐藏多余的内容 一共有两种方式: 设定省略号完整展示 1. 省略号 文本溢出时显示省略号 .item-value {flex-basis: 7…...

three.js PropertyBinding和PropertyMixer
PropertyBinding 对场景图中某一真实属性的引用,内部使用。 构造器 PropertyBinding( rootNode : Object3D, path, parsedPath ) -- rootNode: -- path -- parsedPath (可选) 属性 # .path : Number # .parsedPath : Number # .node : Number # .rootNode …...

ssh远程连接try1账号切换tips
1,创建拥有sudo权限的用户: 在root下 sudo adduser bio sudo vim /etc/sudoers //修改添加如下: bio ALL(ALL) ALL //bio用户就拥有了root权限参考:https://github.com/isLishude/blog/issues/70 2,修改ssh配置 …...

C++之第十二课
课程列表 哎呀呀,失踪人口回归了!(前段时间跑去B站了,久等了) 今天来讲——数组 有一道题是这样的: 有n个数,请输出其中最大的数。 原来我们就要: int a,b,c... 但是——数组…...

Linux硬连接、软连接和复制的区别
硬连接、软连接和复制在Linux系统中的主要区别体现在以下三点: 文件链接的方式文件独立性文件系统的操作上。 一、硬连接 1. 硬连接是通过ln命令创建的,它为文件创建别名,与源文件共享同一inode号码,因此硬连接和源文件实际…...

基于STM32的无人小车自主避障系统设计
文章目录 前言资料获取设计介绍功能介绍设计程序具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设…...

杂牌鼠标侧键设置
X-Mouse Button Control修改侧键基本功能介绍-CSDN博客 下载链接 【X-Mouse汉化版】X-Mouse中文版 v2.19.2 绿色版(支持Win10)-开心电玩 (kxdw.com)...

Android WebView H5 Hybrid 混和开发
对于故乡,我忽然有了新的理解:人的故乡,并不止于一块特定的土地,而是一种辽阔无比的心情,不受空间和时间的限制;这心情一经唤起,就是你已经回到了故乡。——《记忆与印象》 前言 移动互联网发展…...

智源推出下一代检索增强大模型框架MemoRAG
北京智源人工智能研究院与中国人民大学高瓴人工智能学院联合发布了一款创新的人工智能模型框架——MemoRAG。该框架基于长期记忆,旨在推动检索增强生成(RAG)技术的发展,使其能够处理更复杂的任务,而不仅限于简单的问答…...

【AprilTag】视觉定位实战 | 使用 ROS 驱动的 USB 摄像头进行相机标定与 AprilTag 识别
写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…...

[数据集][目标检测]俯拍航拍森林火灾检测数据集VOC+YOLO格式6116张2类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):6116 标注数量(xml文件个数):6116 标注数量(txt文件个数):6116 标注…...

windows10下tomcat安装及配置教程
Apache Tomcat是一个开源的、轻量级的Servlet容器,广泛用于运行Java Web应用程序。以下是Tomcat安装及配置的基本步骤,根据搜索结果整理: 一、安装前的准备工作 确保你的计算机上已经安装了Java Development Kit (JDK),因为Tomc…...

Spring MVC设置请求头和响应头的Header
在Spring MVC中,动态设置请求头和响应头的方法有多种,以下是一些常见的方式: 设置请求头 使用RequestHeader注解 这个注解用于读取请求中的单个HTTP头部值,并将其作为一个参数传递给控制器方法。 RequestMapping("/examp…...

一个基于 laravel 和 amis 开发的后台框架, 友好的组件使用体验,可轻松实现复杂页面(附源码)
前言 随着互联网应用的发展,后台管理系统的复杂度不断增加,对于开发者而言,既要系统的功能完备,又要追求开发效率的提升。然而,传统的开发方式往往会导致大量的重复劳动,尤其是在构建复杂的管理页面时。有…...

HTML讲解(二)head部分
目录 1. 2.的使用 2.1 charset 2.2 name 2.2.1 describe关键字 2.2.2 keywords关键字 2.2.3 author关键字 2.2.4 http-equiv 小心!VS2022不可直接接触,否则!没这个必要,方源面色淡然一把抓住!顷刻炼化&#x…...

Linux(Ubuntu)(终端实现helloworld输出)
一、终端实现gcc编译 1.写好helloworld.h,helloworld.c,main.c后,打开终端,切换到保存这些文件的文件夹的目录,我把这些文件存放在helloworld的文件夹下,所以输入cd ~/helloworld 2.查看该目录下的文件&a…...

开源模型应用落地-qwen模型小试-调用Qwen2-VL-7B-Instruct-更清晰地看世界-集成vLLM(二)
一、前言 学习Qwen2-VL ,为我们打开了一扇通往先进人工智能技术的大门。让我们能够深入了解当今最前沿的视觉语言模型的工作原理和强大能力。这不仅拓宽了我们的知识视野,更让我们站在科技发展的潮头,紧跟时代的步伐。 Qwen2-VL 具有卓越的图像和视频理解能力,以及多语言支…...

【乐企-工具篇】有关乐企发票文件生成- OFD和PDF文件生成
有关乐企发票文件生成- OFD和PDF文件生成 本文主要是实现发票的OFD文件以及PDF文件的生成可以参考具体实现思路,具体情况需要根据自己业务进行改造! 具体的OFD文件模板可以从税局进行下载,下载之后放到resources资源目录下。 代码 package com.ruoyi.output.service.thi…...

llama网络结构及源码
目录 模型初始化 config lm_head transformer wte h rms_1/rms_2 attn c_attn c_proj 线性层mlp ln_f rope_cache mask_cache kv_caches tokenizer tokenizer初始化 tokennizer.encoder 位置编码和mask 确定最大文本长度 建立rope_cache 建立mask_cache …...

828华为云征文|Flexus云服务器X实例部署宝塔运维面板
本次华为云Flexus云服务器X实例部署宝塔运维面板教学,这次是推陈出新啊 之前的云耀云服务器L实例已经很不错了,大力赞叹华为云的 同时感谢华为云提供优惠卷,只能说白嫖真是太棒了 华为云近期正在筹办华为云828企业节活动,90款免…...

计算机网络 8.*结构化布线
第八章 结构化布线 第一节 结构化布线基础 一、认识结构化布线 1.定义:在建筑物或楼宇内安装的传输线路,是一个用于语音、数据、影像和其他信息技术的标准结构化布线系统。 2.任务:使语音和数据通信设备、交换设备和其他信息管理系统彼此相…...

c#的委托、事件
程序目的:实现对一个bool型变量的监视,当数据变化时,调用某一个函数,引申出委托、事件等基础概念。 方法一、在form1的类定义中,定义如下代码,这样定义是最直接的,也非常简单,没有涉…...