LeetCode 76. 最小覆盖子串
Posted 数据结构和算法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 76. 最小覆盖子串相关的知识,希望对你有一定的参考价值。
截止到目前我已经写了 500多道算法题,其中部分已经整理成了pdf文档,目前总共有1000多页(并且还会不断的增加),大家可以免费下载
下载链接:https://pan.baidu.com/s/1hjwK0ZeRxYGB8lIkbKuQgQ
提取码:6666
原理搞懂了,代码就简单多了,但是这里有个关键点,就是怎么记录窗口内的元素,其实很简单,使用一个map就可以,来看下代码。
public String minWindow(String s, String t) {
//把t中的字符全部放到map中
Map<Character, Integer> map = new HashMap<>();
for (char ch : t.toCharArray())
map.put(ch, map.getOrDefault(ch, 0) + 1);
int left = 0;//窗口的左边界
int right = 0;//窗口的右边界
//满足条件的窗口开始位置
int strStart = 0;
//满足条件的窗口的长度
int windowLength = Integer.MAX_VALUE;
while (right < s.length()) {
//记录右指针扫描过的字符
char rightChar = s.charAt(right);
//如果右指针扫描的字符存在于map中,就减1
if (map.containsKey(rightChar))
map.put(rightChar, map.getOrDefault(rightChar, 0) - 1);
//记录之后右指针要往右移
right++;
//检查窗口是否把t中字符全部覆盖了,如果覆盖了,要移动窗口的左边界
//找到最小的能全部覆盖的窗口
while (check(map)) {
//如果现在窗口比之前保存的还要小,就更新窗口的长度
//以及窗口的起始位置
if (right - left < windowLength) {
windowLength = right - left;
strStart = left;
}
//移除窗口最左边的元素,也就是缩小窗口
char leftChar = s.charAt(left);
if (map.containsKey(leftChar))
map.put(leftChar, map.getOrDefault(leftChar, 0) + 1);
//左指针往右移
left++;
}
}
//如果找到合适的窗口就截取,否则就返回空
if (windowLength != Integer.MAX_VALUE)
return s.substring(strStart, strStart + windowLength);
return "";
}
//检查窗口是否把字符串t中的所有字符都覆盖了,如果map中所有
// value的值都不大于0,则表示全部覆盖
private boolean check(Map<Character, Integer> map) {
for (int value : map.values()) {
//注意这里的value是可以为负数的,为负数的情况就是,相同的字符右
// 指针扫描的要比t中的多,比如t是"ABC",窗口中的字符是"ABBC"
if (value > 0)
return false;
}
return true;
}
上面注释已经写的很详细了,基本上也都能看懂,实际上我们还可以把HashMap换成数组,原理其实都是一样的,来看下代码
public String minWindow(String s, String t) {
int[] map = new int[128];
//记录字符串t中每个字符的数量
for (char ch : t.toCharArray())
map[ch]++;
//字符串t的数量
int count = t.length();
int left = 0;//窗口的左边界
int right = 0;//窗口的右边界
//覆盖t的最小长度
int windowLength = Integer.MAX_VALUE;
//覆盖字符串t开始的位置
int strStart = 0;
while (right < s.length()) {
if (map[s.charAt(right++)]-- > 0)
count--;
//如果全部覆盖
while (count == 0) {
//如果有更小的窗口就记录更小的窗口
if (right - left < windowLength) {
windowLength = right - left;
strStart = left;
}
if (map[s.charAt(left++)]++ == 0)
count++;
}
}
//如果找到合适的窗口就截取,否则就返回空
if (windowLength != Integer.MAX_VALUE)
return s.substring(strStart, strStart + windowLength);
return "";
}
以上是关于LeetCode 76. 最小覆盖子串的主要内容,如果未能解决你的问题,请参考以下文章