LeetCode76 MinimumWindowSubstring
题目描述
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
说明:
- 如果 S 中不存这样的子串,则返回空字符串
""
。 - 如果 S 中存在这样的子串,我们保证它是唯一的答案。
示例1:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”
解答
解法:滑动窗口
基本思路:窗口右边界一直右移直到包含所有t中的字符,然后移动左边界寻找最短的子串。同样需要两个额外的空间来记录s的窗口和t中字符的构成情况。具体其实可以看上一篇LeetCode438,也是滑动窗口的题目。只是稍微改了一下更新结果的那个部分。
但是需要注意:字符串s中包含t的意思是,所有的字符,包括出现次数。比如s=“a”,而t=“aa",就应该返回”“,因为s中只有一个a,而t有两个a。
public static String solve(String s, String t){
String result="";
int[] windows = new int[256];
int[] need = new int[256];
int left=0, right=0; //[left,right]为窗口
int len = s.length();
int match =0; //匹配度
int kind = 0; //统计p中出现的字符种类。
int lengthOfWindow=s.length()+1;
int leftResult=0, rightResult=0;
for (int i=0;i<t.length();i++){
need[t.charAt(i)]++;
if(need[t.charAt(i)]==1)
kind++;
}
while (right<len){
char c = s.charAt(right);
windows[c]++;
if (windows[c]==need[c] && need[c]>0){ //出现次数等于t字符串中的出现次数,匹配度才能加一
match++;
}
while (match==kind){
if (right-left+1<lengthOfWindow){ //符合条件的覆盖子串
lengthOfWindow=right-left+1;
leftResult=left;
rightResult=right+1;
}
char leftChar = s.charAt(left);
windows[leftChar]--;
if (windows[leftChar]<need[leftChar] && need[leftChar]>0){
match--;
}
left++;
}
right++;
}
result = s.substring(leftResult,rightResult);
return result;
}