【数组&双指针】LeetCode 76. 最小覆盖子串【困难】
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
提示:
1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?
【分析】
双指针方案。
首先:
(1)用valid表示目标字符窗中每一类字符的个数是否都满足条件;
(2)用hash表need记录目标串中每一个字符的个数;
(3)用hash表window记录当前窗口中,包含的目标字符的个数;
(4)用length记录当前window窗口的长度。
思路:
遍历源字符串,利用双指针,记录窗口的位置,当窗口中每个目标字符的个数与目标字符串中对应字符的个数都相等时,就停止移动右侧指针,开始缩小左侧指针。
缩小左侧指针时,不断更新窗口长度,并更新窗口中每个目标字符的个数,当窗口中目标字符的个数与目标字符串中的对应字符的个数相等时,就减小有效长度,缩小窗口。
注意:
这里,为了避免边界条件的讨论,我们将双指针的查找区间设置为[left, right),即左闭右开的查找区间。
那么,初始化查找区间就是[0, 0],最后一个查找区间就是[left, n)。
这种情况下初始查找区间[0, 0),窗口长度为0,只要右侧指针移动一步,窗口中就包含一个元素,同时,窗口的长度就是length = right - left,比较方便。
class Solution: def minWindow(self, s: str, t: str) -> str: need = dict() # 用hash表need记录目标串中每一个字符的个数 window = dict() # 用hash表window记录当前窗口中,包含的目标字符的个数 # 用need记录所有目标字符的个数; 开始遍历目标字符串 for _char in t: if _char not in need: # 若目标字符串中的字符不在need中,那么need与window均将该字符数目记录为0 need[_char] = 0 window[_char] = 0 need[_char] += 1 # 跳出if条件语句,需要将遍历到的char在need中进行+1记录 left, right = 0, 0 # 用双指针遍历源字符串 valid = 0 # 记录窗口中目标字符的每一类字符是否个数已经满足,满足就加1 start = 0 # 记录窗口的右侧位置 length = len(s) + 1 # 将窗口长度初始化为一个无效值,即大于源字符串的长度值 # 右指针遍历字符串的每一个位置:作为窗口右侧结束位置 while right < len(s): right_char = s[right] right += 1 # 增大窗口 if right_char in need: # 若窗口内的最后一个字符在目标字符串中, 更新窗口中的字符个数 window[right_char] += 1 if need[right_char] == window[right_char]: # 当前字符在窗口中的字符个数与目标字符串的字符个数相等,更新有效长度 valid += 1 # 当窗口中的每一类字符个数都与目标串中的每一类字符个数相等,就不断缩小左侧指针 while valid == len(need): # 更新最小的窗口长度 if right - left < length: start = left length = right - left first_char = s[left] left += 1 # 缩小窗口 # 若左侧字符在目标字符里面 if first_char in need: # 当前字符在窗口中的个数,与目标串个数相等,就减少有效长度 if window[first_char] == need[first_char]: valid -= 1 # 更新窗口中的字符个数 window[first_char] -= 1 return "" if length == len(s) + 1 else s[start:start + length]
相关文章
- SFTP & FTP Upload
- [CSS] Grid: X: justify-content, Y: align-items, X & Y: place-content
- 【数组&双指针】LeetCode 142. 环形链表 II【中等】
- Begin automatic SQL Tuning Advisor run for special tuning task "SYS_AUTO_SQL_TUNING_TASK"
- [Ramda] Pluck & Props: Get the prop(s) from object array
- 【队列&栈】LeetCode 85. 最大矩形【困难】
- 【数组&双指针】LeetCode 76. 最小覆盖子串【困难】
- leetcode每日一题【399. 除法求值】==》并查集&模板
- Unable to read the project file 'client.csproj'. Could not load file or assembly 'Microsoft.Build.En
- Custom tool error: Failed to generate code for the service reference ××××××. Please check other erro
- 华为OD机试 - 寻找符合要求的最长子串(Java & JS & Python)
- 华为OD机试 - 货币单位换算(Java & JS & Python)
- 华为OD机试 - 分苹果(Java & JS & Python)
- 前端命名规范&常用命名名称总结
- ML之LoR&SGD:基于LoR(逻辑回归)、SGD梯度下降算法对乳腺癌肿瘤(10+1)进行二分类预测(良/恶性)
- CloudNative:云原生(分布式云)的简介(发展&演变/为什么需要/优势&价值/安全/对比传统企业应用)、四大核心技术、CNCF云原生交互景观、云原生技术的使用经验及方法之详细攻略
- TF之data_format:data_format中的NHWC&NCHW简介、转换的详细攻略
- Collectors.reducing总结&Collectors.mapping+Collectors.reducing+TreeSet等等
- <LeetCode OJ> 328. Odd Even Linked List
- Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析&Redis分布式锁的正确使用姿势!...
- Please ensure that adb is correctly located at 'D:Androidandroid-sdkplatform-toolsadb.exe' and
- C# DataTable&DataSet
- TEE&TrustZone
- LeetCode刷题训练 && LeetCode算法和数据结构学习(一)