专题二 - 滑动窗口 - leetcode 76. 最小覆盖子串 | 困难难度

leetcode 76. 最小覆盖子串

  • leetcode 76. 最小覆盖子串 | 困难难度
    • 1. 题目详情
      • 1. 原题链接
      • 2. 基础框架
    • 2. 解题思路
      • 1. 题目分析
      • 2. 算法原理
      • 3. 时间复杂度
    • 3. 代码实现
    • 4. 知识与收获

在这里插入图片描述

leetcode 76. 最小覆盖子串 | 困难难度

1. 题目详情

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

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

示例 1:
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
解释:最小覆盖子串 “BANC” 包含来自字符串 t 的 ‘A’、‘B’ 和 ‘C’。

示例 2:
输入:s = “a”, t = “a”
输出:“a”
解释:整个字符串 s 是最小覆盖子串。

示例 3:
输入: s = “a”, t = “aa”
输出: “”
解释: t 中两个字符 ‘a’ 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:
m == s.length
n == t.length
1 <= m, n <= 105
s 和 t 由英文字母组成

进阶:你能设计一个在 o ( m + n ) o(m+n) o(m+n)时间内解决此问题的算法吗?

1. 原题链接

leetcode 76. 最小覆盖子串

2. 基础框架

● Cpp代码框架

class Solution {
public:string minWindow(string s, string t) {}
};

2. 解题思路

1. 题目分析

( 1 ) (1) (1) 本题要求 找s中涵盖t中所有字符的最短子串。这里涵盖的意思就是不小于,即大于等于的意思。只要找到s的子串满足t中字符频次小于等于s子串字符频次,对于存在于s子串中而在t中不存在的字符则没有要求。
( 2 ) (2) (2) 本题要求返回的结果是一个字符串,为了方便表示一个字符串,我们使用起始下标begin,字符串长度minlen就能表示在s中的任意一个子串。
( 3 ) (3) (3) 首先想到暴力枚举 + 字符哈希表思路:
哈希表1hash1记录t串中字符频次;哈希表2hash2记录s的子串中字符频次;
对字符串s,下标left[0, s.size-1]依次作为子串的起始位置,下标rightleft开始遍历s,每次字符放入哈希表2hash2
然后遍历两个哈希表,以哈希表2hash2为标准,判断hash2中字符频次是否小于等于hash1
——如果小于说明当前[left, right]子串是满足要求的
————在子串满足要求的基础上再次判断当前子串的长度是否比记录的最小长度minlen小,如果小就更新minlen = right - left + 1,begin = l,如果大就不更新;
————在这种情况下,以当前left为起始,right之后的位置为结束的子串也一定是符合题意的,串的长度一定都是大于当前串right-left+1的,所以没有了判断的必要,left可以直接右移,right也回到left位置开始下一次遍历;
——如果大于则当前子串不满足要求,right继续向右移动;
( 4 ) (4) (4)
在这里插入图片描述

2. 算法原理

( 1 ) (1) (1) 单调性 - 引出滑动窗口
在以left为起点,right为末尾的s子串中,假设在某一个位置right元素加入到哈希表2hash2中后子串恰好满足了t字符频次都小于子串对应字符频次的要求。
之后left会向右移动1位,我们来讨论一下right是否需要回退到新left位置:
已知在[left, right]的s子串恰好满足要求,之后left右移1位,假设left先不右移,那么[left + 1, right]只有2种情况:

  1. left位置元素恰好是t中字符,且hash2[s[left]] == hash1[s[left]],那么left右移将会导致hash2中left位置字符频次小于t对应字符。所以right回退到left之后还是会遍历到元来的位置且会继续向后遍历,此时right没有回退的必要;
  2. left位置元素不是t中字符,那么left +1, righ]的子串依然是恰好满足要求的,所以right回退left位置继续遍历还是会回到原来的位置并且right不需要继续向后移,因为会继续以[left+1,right]子串更新结果。
    ( 2 ) (2) (2) 滑动窗口 + 哈希表
    ( 3 ) (3) (3) 初始化:left = 0, right = 0, begin = -1, minlen = INT_MAX;
    ( 4 ) (4) (4) 进窗口:in = s[right], hash2[in]++;
    ( 5 ) (5) (5) 判断:遍历两个哈希表,判断相等时
    ( 6 ) (6) (6) 更新结果:在minlen > right - left + 1时,begin = l, minlen = right - left + 1;
    ( 7 ) (7) (7) 出窗口:out = s[left], hash2[left]- -, left- -;
    ( 8 ) (8) (8)right++;

( 2 ) (2) (2) 滑动窗口 + 哈希表 + 有效字符种类计数
有效字符种类计数的引入是为了优化判断时总是遍历哈希表的:
我们定义有效字符种类计数count:
只有在s子串对应字符频次等于t中对应字符频次时count才计数。而其他大于小于或者字符直接不在t中都不进行计数。

( 3 ) (3) (3) 初始化:left = 0, right = 0, begin = -1, minlen = INT_MAX, count =0;
( 4 ) (4) (4) 进窗口:in = s[right], hash2[in]++;
在hash2[in] == hash1[in]时,count++;//维护count
( 5 ) (5) (5) 判断:count == hash1.size时
( 6 ) (6) (6) 更新结果:在minlen > right - left + 1时,begin = l, minlen = right - left + 1;
( 7 ) (7) (7) 出窗口:
out = s[left];
在hash2[out] == hash1[out] 时,count–;//维护count
hash2[left]- -, left- -;

( 8 ) (8) (8)right++;

3. 时间复杂度

暴力枚举 + 哈希表 O ( n 2 ∗ m ) O(n^2*m) O(n2m)

枚举所有子串,需要两层循环,n^2,每次循环内需要判断两个哈希表是否相等,通过遍历长度为m的哈希表判断。

滑动窗口 + 哈希表 O ( n + m ) O(n+m) O(n+m)

left和right遍历一遍s字符串,是n;每次遍历都要判断两个哈希表是否相等,是m;

滑动窗口 + 哈希表 + 有效字符计数 O ( n ) O(n) O(n)

left和right遍历一遍s字符串,是n,判断时通过有效字符种类计数count变量直接判断;

3. 代码实现

class Solution {
public:string minWindow(string s, string t) {string ret;int hash1[128] = { 0 };int kinds = 0;for(auto& e : t) if(hash1[e]++ == 0) kinds++;int hash2[128] = { 0 };int n = s.size();int l = 0, r = 0;int count = 0;// 有效字符的种类int begin = -1, minlen = INT_MAX;while(r < n){char in = s[r];hash2[in]++;// 进窗口if(hash2[in] == hash1[in]) count++;//维护countwhile(count == kinds){// 判断if(minlen > r - l + 1) {// 更新结果minlen = r - l + 1;begin = l;}char out = s[l++];if(hash2[out]-- == hash1[out]) count--;// 维护count}r++;}cout << begin << " " << minlen << " ";return begin != -1 ? s.substr(begin, minlen) : "";}
};

4. 知识与收获

( 1 ) (1) (1)
( 2 ) (2) (2)
( 3 ) (3) (3)


T h e The The E n d End End

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

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

相关文章

如何在Windows11中安装Multipass并启动一个Ubuntu22的虚拟机(以失败告终)

使用了很长时间的VMWare&#xff0c;感觉没有什么特别不好的。不过由于最近需要做uniapp开发&#xff0c;这玩意在Windows中适配的最好&#xff0c;这个时候用VMWare虚拟机就不合适了。但是&#xff0c;我又要在Win11中写uniapp的代码&#xff0c;又要写Python的代码&#xff0…

结构体之成绩统计2

题目描述 有N个学生,每个学生的数据包括学号、姓名、3门课的成绩,从键盘输入N个学生的数据,要求打印出3门课的总平均成绩,以及最高分的学生的数据(包括学号、姓名、3门课成绩) 输入格式 学生数量N占一行每个学生的学号、姓名、三科成绩占一行,空格分开。 输出格式 各门…

操作系统总结(第二周 第一堂)

前言&#xff1a; 第一周的重点就在于一张图表&#xff1a; 基于这张图&#xff0c;我们将陷入内核分为了两个大块Trap和Interrupt。同时我们知道一件事情任何一次I/O操作或者错误程序操作都将陷入内核&#xff0c;从而使得内核可以监控所有的外部设备以及维护整个电脑程序运行…

柜面服务能力演讲及岗位技能大赛活动方案

为提升柜面服务能力及员工专业能力&#xff0c;助力业务发展&#xff0c;聚力推进“柜面焕新升级”活动&#xff0c;进一步为销售一线提供及时、高效、顺畅、快捷的服务支持&#xff0c;省公司将组织开展“凝聚你我力量&#xff0c;共助业务发展”演讲及岗位技能大赛活动&#…

C语言——动态内存分配

前言&#xff1a;通过前面的学习&#xff0c;我们知道C语言中在内存中开辟空间的方法有&#xff1a;变量和数组。既然拥有了开辟空间的方法&#xff0c;我们为什么还要学习动态内存分配呢&#xff1f; int val 20; //在内存中开辟四个字节的空间 int arr[10] { 0 }; //在内…

如何在Linux部署DataEase数据分析服务并实现无公网IP远程分析内网数据信息

文章目录 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 前言 DataEase 是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务…

mysql数据库:使用 bash脚本 + 定时任务 自动备份数据

mysql数据库&#xff1a;使用 bash脚本 定时任务 自动备份数据 1、前言2、为什么需要自动化备份&#xff1f;3、编写备份脚本4、备份脚本授权5、添加定时任务6、重启 crond / 检查 crond 服务状态7、备份文件检查 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏…

【代码随想录】【二叉树】补day21:二叉搜索树的最小绝对差 、二叉搜索树中的众数 、二叉树的最近公共祖先

最小绝对差 1.申请一个数组&#xff0c;比较两两之间最小的差值 def getresult3(self,node:TreeNode):self.nums[]self.getMinimumDifference(node)mindifferencefloat(inf)for i in range(len(self.nums)-1):mindself.nums[i1]-self.nums[i]if mindifference>mind:mindiff…

U盘打不开怎么办?专家解析原因与数据恢复之道

一、遭遇困境&#xff1a;U盘突然无法访问 在日常生活和工作中&#xff0c;U盘作为重要的数据存储和传输工具&#xff0c;其稳定性和可靠性至关重要。然而&#xff0c;有时我们会突然遭遇U盘打不开的困境&#xff0c;这无疑令人感到焦虑和困惑。当我们将U盘插入电脑时&#xf…

U盘文件夹变exe,数据恢复与防范全攻略

在日常使用U盘的过程中&#xff0c;不少用户都遭遇过这样一个令人头疼的问题&#xff1a;原本整齐有序的文件夹突然变成了exe可执行文件。这种异常情况不仅影响了文件的正常访问&#xff0c;更可能隐藏着数据丢失的风险。本文将深入探讨U盘文件夹变exe现象的背后原因&#xff0…

OSCP靶场--BlackGate

OSCP靶场–BlackGate 考点(1.redis rce 2. CVE-2021-4034提权) 1.nmap扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC -p- 192.168.163.176 --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-14 03:32 EDT Nmap scan report for 192.168.163.…

《LeetCode热题100》笔记题解思路技巧优化_Part_3

《LeetCode热题100》笔记&题解&思路&技巧&优化_Part_3 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题链表&#x1f7e2;1. 相交链表&#x1f7e2;2. 反转链表&…