题目描述:给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
分析:
明显是要使用滑动窗口,比较复杂的一点是,滑动窗口的长度是可变的。
所以区别于固定滑动窗口的达到窗口长度后随着右指针向右移动一位左指针也要移动一位
滑动窗口更改长度的原因是在滑动窗口中去掉不需要的字符
举个例子:S=ADOBECODEBANC,T=ABC,首先一直向后走,
此时滑动窗口中为ADOBECODEB,hash数组中hash[A]=0,hash[B]=-1,hash[C]=0,hash[D]=-2,hash[E]=-2,hash[O]=-1,
继续向右走,当我们右指针走到第二个A的时候ss[left]=-1,
就应该把第一个A去掉,同时,要去掉T中没有的:DO,也去掉T中虽然有但我们后面(滑动窗口中)已经有了的:B,之后继续去掉T中不需要的:E,
这时left应该指向C,然后就不继续动了。此时滑动窗口中字符串为CODEBA,right继续向后走
走到N无所谓,走到C时,又要继续挪动我们的滑动窗口,
同理,去掉CODE。于是此时滑动窗口为BANC。
举个另一个的例子,S=DOBECODEBANC,T=ABC,当left指向D,right指向O时,(left指向的也是T中不需要的,所以应该右移左指针),
以代码来看:
hash[D]=-1,因此也要让left右移,直到找到一个滑动窗口中需要的字符或left已经等于right
核心思想:始终让left指向T中需要的字符或者已经指向了right。
代码:
class Solution {
public String minWindow(String s, String t) {
char[] ss = s.toCharArray();
char[] tt = t.toCharArray();
//用来存储滑动窗口中的值(注意还有小写的)
int[]hash = new int[256];
//最小子串的长度
int minlength = s.length();
//最小子串
String results = "";
for(char smallt:tt)
{
hash[smallt-'0']++;
}
int left = 0;
int right = 0;
int count = tt.length;
for(;right<ss.length;right++)
{
hash[ss[right]-'0']--;
//说明当前的字符存在于T中,且当前滑动窗口中还需要该字符
//后面这个且的意思就是比如我的T为ABC,我只有第一次遇到A才会count--,而第二次就不会了,
if(hash[ss[right]-'0']>=0)
{
count--;
}
//right又遇到了left处的字符(特指遇到T中存在的),或left处的字符不是T中需要的,就右移左指针直到找到需要的或者left=right
while(left<right&&hash[ss[left]-'0']<0)
{
hash[ss[left]-'0']++;
left++;
}
//这里大于等于是防止最小覆盖子串就是s其本身
if(count==0&&minlength>=right-left+1)
{
minlength = right-left+1;
results = s.substring(left,right+1);
}
}
return results;
}
}
作者:coder_hezi
链接:https://leetcode-cn.com/problems/minimum-window-substring/solution/hua-dong-chuang-kou-suan-fa-chao-xiang-xi-jie-xi-k/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。