「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」
前言
力扣第七十六题 最小覆盖子串 如下所示:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
- 对于
t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量。 - 如果
s中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"
示例 2:
输入: s = "a", t = "a"
输出: "a"
一、思路
题目稍微有点长,我们可以从中得到以下的关键信息:
- 子字符串中字符数量应大于等于
t中的数量 - 需要找到该
最小覆盖子串并输出
我们需要注意 最小覆盖子串 中是有可能会有重复字符的,例如 s = "ECABAD", t = "ABCD" 的最小覆盖子串是 CABAD。
假设 i ~ j 中间包含了字符串 t 所需的字符,那么如何找到最小覆盖子串呢?
大致的实现步骤,如下所示:
- 遍历字符串
t并将各字符计数,便于后续判断 - 遍历字符串
s,判断当前字符是否包含t- 如果不包含:继续向下遍历
- 如果包含:丢弃左边第一个必要的字符
- 返回结果即可
举个例子
此处以示例中的 s = "ADOBECODEBANC", t = "ABC" 作为例子
- 遍历
t并计数,得到所需的字符个数 - 开始遍历字符串
s - 当
i = 5时,子串ADOBEC含有ABC。更新结果为ADOBEC - 丢弃子串
ADOBEC左边首个必要元素,丢弃后为DOBEC - 再继续向右便利,当
i=10时,此时子串的长度不小于当前结果,故丢弃。 - 重复上述的过程,值得注意的是:在找到子串后,如果丢弃了非必要字符,需要判断是否需要更新结果
- 最终可以找到最小覆盖子串
BANC
二、实现
实现代码
实现代码与思路中保持一致
public String minWindow(String s, String t) {
HashMap<Character,Integer> need = new HashMap<>(); // 需要的字符及数量
HashMap<Character,Integer> had = new HashMap<>(); // 当前字串中出现的字符及数量
// 初始化需要的字符数量
for(int i = 0;i < t.length();i ++){
need.put(t.charAt(i),need.getOrDefault(t.charAt(i), 0) + 1);
}
String ans = "";
int len = Integer.MAX_VALUE;
int cnt = 0; // 当前子串有多少有效字符
// 窗口向右滑动
int left = 0, right = 0;
while (right < s.length()) {
// 向右扩展
char c = s.charAt(right);
had.put(c, had.getOrDefault(c, 0) + 1); // 已有的字符串中计数
if(need.containsKey(c) && had.get(c) <= need.get(c)) {
cnt ++;
}
if (cnt == t.length()) { // 如果找到了结果
if (right -left + 1 < len) {
len = right - left + 1;
ans = s.substring(left, right+1);
}
// 向右压缩
while (left < right){
char leftC = s.charAt(left);
had.put(leftC, had.get(leftC) -1);
left++;
// 找到第一个必要元素丢弃
if (need.containsKey(leftC) && had.get(leftC) < need.get(leftC)) {
cnt--;
break;
} else { // 比较结果
if (right -left + 1 < len) {
len = right - left + 1;
ans = s.substring(left, right+1);
}
}
}
}
right++;
}
return ans;
}
测试代码
public static void main(String[] args) {
new Number76().minWindow("ADOBECODEBANC", "ABC");
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~