76. 最小覆盖子串¶
最后更新:2024-05-10-22
链接:https://leetcode.cn/problems/minimum-window-substring/description/
题目描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案。
题目示例
输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"
解释: 最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'
输入: s = "a", t = "a"
输出: "a"
解释: 整个字符串 s 是最小覆盖子串
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,因此没有符合条件的子字符串,返回空字符串。
提示:
- \(m == s.length\)
- \(n == t.length\)
- \(1 <= m, n <= 10^5\)
- s 和 t 由英文字母组成
进阶
你能设计一个在 o(m+n) 时间内解决此问题的算法吗?
解题思路
使用滑窗思想,在判断上做优化
最先的时候使用滑窗算法做的,跟官方的方法一样,每次都是去判断得到的子串是否是满足条件的最小子串,判断的方法就是比较:
C | |
---|---|
这是一个很笨的办法,题是做出来了,只是最后一个用例超时了。因此,想了各种的优化。。。。。
后来,看了其他同学的题解,有下面这么一个优化算法,大概思想如下:
- T字符串中,所有字符的个数就是T字符串的长度;
- 我们从S字符串中找到在T字符串中出现的字符,然后计数,遇到计数超过T的就跳过当次的,最后当计数值=len(T)的时候,就找到了我们需要的子串。
这样描述可能不太好理解,我们举个例子:
输入: AAAAAABBBBBBCCCCCC ABC
- 对于这个数据,我们从开头计数,遇到第一个A,计数sum_s + 1, count_s['A']++;
- 继续,遇到第二个A的时候,因为count_s['A'] >= count_T['A'],我们不对第二个A计数,sum_s保持不变,继续往后;
- 同样的,对第一个B计数,后面的B不计数,第一个B的时候,sum_s + 1;然后遇到第一个C的时候,sum_s +1;
- 这个时候,sum_s = 3, 刚好=len(T)
再看看我们取到的子串AAAAAABBBBBBC, 刚好是满足条件的一个子串。
然后对于这个子串,我们再从左侧开始,删除count_s['A'] > count_t['A']的部分,使得count_s['A'] = count_t['A'],得到子串ABBBBBBC,这就是我们得到的一个满足条件的子串,依次类推,直到我们找到最小的那个。
以题目示例为例:
- 输入:ADOBECODEBANC ABC
- 第一轮,我们找到ADOBEC;
- 第二轮,我们找到DOBECODEBA, 然后去掉左侧的无效字符,得到CODEBA;
- 第三轮,我们找到BANC, 两边都没有要去掉的,然后看长度,这个就是我们需要的最小值。
Go | |
---|---|