最小覆盖子串

Posted xbc121

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小覆盖子串相关的知识,希望对你有一定的参考价值。

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。

示例:

输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:

如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:这题和字符串的子串相关,想到用滑动窗口算法,因为只需要改变窗口两端的元素,且窗口内的全部元素都是有用的。指针i和j分别指向窗口的头和尾,当窗口内的子串满足要求,则让i向右移动,否则让j向右移动,直到j移动到S的最后一个字符处。一开始窗口中的元素个数为0,要将j向右移动直到满足要求或者移动到S的最后一个字符处为止。这题的最大难点在于如何在窗口滑动的同时判断窗口中的子串是否符合条件。想了一下午,一开始的思路是用一个函数来判断T中所有字符是否被包含在了窗口中,函数的参数就是窗口内的子串和T,但是这样超出了时间限制。于是看了题解,题解代码如下:

class Solution {
public String minWindow(String s, String t) {
//由于字符类型,就考虑所有的ASCII码,因此直接用128个长度的数组代替原来的HashMap,提高性能
//用来统计t中每个字符出现次数
int[] needs = new int[128];
//用来统计滑动窗口中每个字符出现次数
int[] window = new int[128];
//统计t中每个字符出现次数
for (char ch : t.toCharArray()) {
needs[ch] = needs[ch]+1;
}
int l = 0, r = 0;
int plength = t.length();
//候选字符数
int count = 0;
int minLength = s.length()+1;
String result = "";
while (r < s.length()) {
char ch = s.charAt(r);
//统计滑动窗口中每个字符出现次数
window[ch] = window[ch]+1;
// 当这个字符是在t中,并且t需要的次数大于等于该字符在滑动窗口出现的次数,被确定为候选字符。
if (needs[ch] > 0 && needs[ch] >= window[ch]) {
count++;
}
//当候选字符数等于t的长度时,说明滑动窗口中的字符串包含T,开始移动l,缩小窗口
//直到不满足count == plength时,继续扩展窗口
while (count == plength){
ch = s.charAt(l);
if (needs[ch] > 0 && needs[ch] >= window[ch]){
count--;
}
//找出长度最短符合条件的结果 (r-l)+1计算当前窗口大小
if ((r-l)+1 < minLength){
minLength = (r-l)+1;
result = s.substring(l,r+1);
}
window[ch] = window[ch]-1;
l++;
}
r++;
}
return result;
}
}

作者:wky181
链接:https://leetcode-cn.com/problems/minimum-window-substring/solution/javahua-dong-chuang-kou-dai-ma-you-xiang-xi-zhu-sh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其实在while(count==plength)当中,可以把if ((r-l)+1 < minLength)提到最前面。

以上是关于最小覆盖子串的主要内容,如果未能解决你的问题,请参考以下文章

76. 最小覆盖子串 完整题解 刷题笔记

76. 最小覆盖子串 完整题解 刷题笔记

5-106-(LeetCode- 76) 最小覆盖子串

Leetcode 76.最小覆盖子串

[leetcode] 76. 最小覆盖子串

76. 最小覆盖子串