LeetCode - 76 最小覆盖子串

news/2024/4/29 15:02:02/文章来源:https://blog.csdn.net/qfc_128220/article/details/128092566

目录

题目来源

题目描述

示例

提示

题目解析

算法源码


题目来源

76. 最小覆盖子串 - 力扣(LeetCode)

题目描述

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例

输入s = "ADOBECODEBANC", t = "ABC"
输出"BANC"
说明
输入s = "a", t = "a"
输出"a"
说明
输入s = "a", t = "aa"
输出""
说明t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示

  • 1 <= s.length, t.length <= 10^5
  • s 和 t 由英文字母组成

题目解析

本题要求的最小覆盖子串的含义是:包含某些指定字符,且要求最短的子串。

即题目要我们在s字符串中,找到一个子串,这个子串需要包含t字符串中所有字符,这样的子串有很多,我们需要其中最短的那个子串。

本题最容易想到的解法是滑动窗口,滑动窗口运动逻辑如下:

需要注意的是这里的滑动窗口是不定长的滑动窗口。

 

 

 

 

 

 以上就是变长滑动窗口的运动逻辑。

我们可以总结如下:

滑动窗口的范围即:左右指针的范围,初始时左右指针都指向索引0位置,

  • 如果滑动窗口内部没有包含了t中所有字母,则右指针向右移动一格,然后继续判断滑动窗口内部是否包含了t中所有字母。
  • 如果滑动窗口内部包含了t中所有字母,(此时滑动窗口就是一个满足要求的子串,我们将他记录下来),则左指针向右移动一格,然后继续判断滑动窗口内部是否包含了t中所有字母。

按照上面逻辑,我们可以将记录的子串比较长度,保留最短的作为题解。

通过上面总结,我们似乎发现逻辑并不复杂,我们可以按照上面逻辑实现一下:

/*** @param {string} s* @param {string} t* @return {string}*/
var minWindow = function (s, t) {if(s.length < t.length) return ''let l = 0let r = 0const ans = []while(r < s.length) {const subStr = s.substring(l,r+1)if(contain(subStr, t)) {ans.push(subStr)l++} else {r++}}if(!ans.length) return ''return ans.sort((a,b) => a.length - b.length)[0]
};function contain(str, subStr) {const sup = {}for(let c of str) {sup[c] ? sup[c]++ : (sup[c]=1)}const sub = {}for(let c of subStr) {sub[c] ? sub[c]++ : (sub[c]=1)}let flag = truefor(let c in sub) {if(!sup[c] || sub[c] > sup[c]) {flag = falsebreak}}return flag
}

 但是结果却是超时,原因是我们算法的时间复杂度达到了O(n^2),而数量级1 <= s.length, t.length <= 10^5,最终会有10^10次循环,这是肯定超时的。

我们可以看下上面的代码,找找那部分是可以优化的?

答案是contain函数,这个函数的作用是验证滑动窗口内部是否包含t字符串中所有字符的,但是方法比较笨,每当滑动窗口位置改变,就会重新统计字符数量,然后比较。这其中必然存在大量重复统计工作。

利用滑动窗口解决问题,我们一定要学会差集思想,因为滑动窗口的移动是有规律的,比如每次向右移动一格,这样本轮滑动窗口状态和上一轮滑动窗口状态,必然存在交集区域,如下图BC就是两次滑动窗口的交集区域

 交集区域我们是不需要关注的,只需关注差集区域,如上图A和D,本轮滑动窗口,相当于在上一轮滑动窗口的基础上,删除了一格A,增加了一格D,这样的话,统计本轮滑动窗口内容,就不需要O(n)时间,只需要O(1)时间了。

对于本题,滑动窗口的运动规律要复杂一点,并字符数量统计也不简单。

首先,我们需要统计字符串t中各字符的数量,比如t="ABC",则统计结果为count: {A:1, B:1, C:1},并记录总数量为len = t.length。

然后开始滑动窗口运动:

滑动窗口运动中新增的字符c(即右指针向右移动一格后新增的内容),如果在t中,即count[c]存在,则count[c]--,那么此时len要不要也自减呢?

我们看两种情况:

用例1:

s = "ADOBECODEBANC", t = "ABC"

情况1:

 此时右指针指向的字符A,在t中存在,因此count[c]--,count: {A:0, B:1, C:1},此时应该len--,即len变为2。

情况2:

 此时右指针指向的字符“B”,在t中存在,因此count[c]--,count: {A:1, B:-1, C:0},此时滑动窗口内部含有了两个B,但是这并不能意味着需要len也减去1,对于len来说,最多只能减去统计到B个数,如果B个数超出统计个数,即count[B] < 0,此时len不应该自减。

上面是右指针运动中的特殊情况处理,对应的还有左指针运动逻辑处理:

左指针运动,必然是找到了符合要求的子串,即滑动窗口内部含有了所有t字符,此时左指针右移一格,如上图,此时失去了A,而A刚好是t字符串内的字符,即count[A]存在,此时应该count[A]++,即将count:{A:0, B:0, C:0} 变为 count:{A:1, B:0, C:0},而此时也应该len++。

 

但是对于

此时情况是,上面的滑窗的count: {A:0, B:-1, c:0}

当上面滑窗左指针右移一格后,变为下面的滑窗时,失去了B,刚好时t中字符,因此count[B]++,

此时 count: {A:0, B:0, c:0},那么此时len是否也要自增1呢?答案是不需要,因为失去的B是超出统计个数的,因此失去了不需要作任何处理。

算法源码

/*** @param {string} s* @param {string} t* @return {string}*/
var minWindow = function (s, t) {let len = t.length;const count = {};for (let c of t) {count[c] ? count[c]++ : (count[c] = 1);}let i = 0;let j = 0;let minLen = s.length + 1; // 最短子串的长度let start = 0; // 最短子串的起始位置while (j < s.length) {const jc = s[j];if (count[jc]-- > 0) { // 注意:这里count[c]--必须写在if条件中,因为count[jc]可以是负数,但是len不能是负数len--;}while (len === 0) {if (minLen > j - i + 1) {minLen = j - i + 1;start = i;}const ic = s[i];if (count[ic]++ >= 0) { // 注意:这里count[c]++必须写在if条件中,因为len只有在count[c]大于等于0时才能增加len++;}i++;}j++;}return minLen < s.length + 1 ? s.substring(start, start + minLen) : "";
};

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

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

相关文章

iClient for Leaflet设置地图掩膜

作者&#xff1a;lly 文章目录背景一、实现思路二、步骤代码三、完整代码背景 最近很多小伙伴需要只展示地图的某个行政区域&#xff0c;由于地图存在多个图层&#xff0c;所以图层过滤的方式并不能很好的适用&#xff0c;这个时候&#xff0c;我们可以考虑给地图覆盖一层掩膜…

界面控件DevExpress WPF的主题设计器,可轻松完成应用主题研发

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 DevExpress WPF的The…

双十二薅羊毛!这几款数码好物不可错过

双十二即将开始&#xff0c;在这段时间里有的人已经将自己心仪的塞满了整个购物车了吧&#xff0c;而有的人还没想好到底要入手什么&#xff0c;如果你也是还在纠结的话&#xff0c;不知道该买什么又或是想知道哪些产品更适合你入手&#xff0c;不妨来看看小编今天为你带来的这…

MySQL第一弹

目录 一、数据库的基本概念 1、数据 (Data) 2、表 3、数据库 4、数据库管理系统(DBMS) 5、数据库系统 6、DBMS的工作模式如下 二、数据库的发展史 1.第一代数据库&#xff08;淘汰&#xff09; 2.第二代数据库&#xff08;现在用的基本上都是二代&#xff09; 3.第…

亲戚小孩月薪17k,而我只有4k+,好慌......

我们总是在悲观与乐观中反复折磨自己&#xff0c;感觉自己一事无成。总是眼高手低&#xff0c;总以为大运会砸到自己&#xff0c;遇到挫折就会感到很沮丧。 大学四年没考到英语六级证书&#xff0c;小学教资考了两次。现在想要考研&#xff0c;但总是觉得来不及&#xff0c;或…

磁盘划分和磁盘格式化

文章目录列出装置的 UUID 等参数parted 列出磁盘的分区表类型与分区信息磁盘分区&#xff1a;gdisk、fdisk用 gdisk 新增分区槽用 gdisk 删除一个分区槽磁盘格式化&#xff08;建立文件系统&#xff09;XFS 文件系统 mkfs.xfsXFS 文件系统 for RAID 效能优化&#xff08;Option…

java中csv导出-追加-列转行

1、问题描述 业务数据量比较大&#xff0c;业务上查询条件写入数据库&#xff0c;java定时去读&#xff0c;然后导出csv&#xff0c;供用户下载&#xff0c;因为有模板要求&#xff0c;前一部分是统计信息&#xff0c;后一部分是明细信息&#xff1b;首先csv中写入统计信息&am…

IDEA的日常快捷键大全

更多内容在&#xff1a;https://javaxiaobear.gitee.io/ ​​​​​​第1组&#xff1a;通用型 说明 快捷键 复制代码-copy ctrl c 粘贴-paste ctrl v 剪切-cut ctrl x 撤销-undo ctrl z 反撤销-redo ctrl shift z 保存-save all ctrl s 全选-select all …

Python连接Clickhouse遇坑篇,耗时一天成功连接!

首先&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;不要看网上那些乱七八糟的使用clickhouse-driver连接了&#xff0c;真tm难用&#xff0c;端口能搞死你那种&#xff0c;超级烦&#xff01; 推荐直接看官方…

数商云SRM系统招标流程分享,助力建筑材料企业降低采购成本,提高采购效率

近年来&#xff0c;随着主管部门对房地产市场的监管非常严格&#xff0c;房地产业的发展已进入瓶颈期&#xff0c;这对与房地产业密切相关的建材行业产生了很大的影响。同时&#xff0c;我国城市化进入成熟期&#xff0c;行业规模发展动力减弱&#xff0c;建材行业增长压力明显…

Kotlin高仿微信-第8篇-单聊

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

VauditDemo靶场代码审计

靶场搭建 将下载好的VAuditDemo_Debug目录复制到phpstudy的www目录下&#xff0c;然后将其文件名字修改成VAuditDemo&#xff0c;当然你也可以修改成其他的 运行phpstudy并且访问install目录下的install.php&#xff0c;这里我访问的是http://127.0.0.1/VAuditDemo/install/in…

竞赛——【蓝桥杯】2022年12月第十四届蓝桥杯模拟赛第二期C/C++

1、最小的2022 问题描述 请找到一个大于 2022 的最小数&#xff0c;这个数转换成二进制之后&#xff0c;最低的 6 个二进制为全为 0 。 请将这个数的十进制形式作为答案提交。 答案提交 这是一道结果填空的题&#xff0c;你只需要算出结果后提交即可。本题的结果为一个整数…

Java学习之继承练习题

目录 第一题 代码 输出流程分析 运行结果 考察知识点 第二题 代码 流程分析 运行结果 第三题 题目要求 我的代码 代码改进 第一题 代码 package com.hspedu.extends_.exercise;public class ExtendsExercise01 {public static void main(String[] args) {B b new …

Sentinel-2(哨兵2数据介绍)

哥白尼 Sentinel-2&#xff08;哨兵 2&#xff09;计划是一个由两颗相同的 Sentinel-2 极轨卫星组成的星座&#xff0c;两颗卫星相位差 180&#xff0c;运行在平均高度 786 km 的太阳同步轨道上。每颗卫星在其轨道上的位置由双频全球导航卫星系统&#xff08;GNSS&#xff09;接…

ggrcs 包2.4绘制RCS(限制立方样条图)实际操作演示(1)

ggrcs 包2.4版本已经发布一段时间了&#xff0c;大概几个月了吧&#xff0c;收到不少好评&#xff0c; 没听说太大的问题&#xff0c;最主要的问题有两个&#xff1a; 1.是说变量不是数字变量。 2.是说数据超过10万&#xff0c;无法处理 第一个问题非常好处理&#xff0c;这…

R语言MCMC:Metropolis-Hastings采样用于回归的贝叶斯估计

全文链接&#xff1a;http://tecdat.cn/?p19664 MCMC是从复杂概率模型中采样的通用技术。蒙特卡洛马尔可夫链Metropolis-Hastings算法&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。问题如果需要计算有复杂后验pdf p&#xff08;θ| y&#xff09;的随机变量…

简单聊聊什么是react-redux,它能解决哪些问题

或许 在大多数人眼中 redux是一个相对复查很多的知识点 但确实如果你熟悉了流程 其实也比较简单的 redux是一个数据管理方案 我们先来举个例子 目前我们知道 react中有两种组件数据通信的方式 分别是 props 父传子 定义事件 子传父 通过事件将自己的数据传给父级 那如果是兄弟…

领悟《信号与系统》之 周期信号的傅里叶变换计算

周期信号的傅里叶变换计算一、周期信号的傅里叶变换存在的条件二、周期信号的傅里叶变换例题&#xff1a;一、周期信号的傅里叶变换存在的条件 典型非周期信号&#xff08;如指数信号&#xff0c;矩形信号等&#xff09;都是满足绝对可积&#xff08;或绝对可和&#xff09;条…

一种高选择性和灵敏的荧光生物标记物,可用于标记碱性磷酸酶 (ALP),5-FAM-Alkyne,510758-19-7,荧光生物标记物

【中文名称】5-羧基荧光素-炔烃【英文名称】 FAM alkyne,5-isomer&#xff0c;5-FAM alkyne【结 构 式】 【CAS号】510758-19-7 【分子式】C24H15NO6【分子量】413.39【基团】炔基基团【纯度】95%【规格标准】5mg&#xff0c;10mg&#xff0c;25mg&#xff0c;包装灵活&#x…