最小覆盖子串
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
此题最大的收获应该是使用一个freq变量记录字符数组中每个字符出现的次数。
如果是字符数组,也可以使用定义的int型数组,编译器会根据字符的ASCII码将字符转换成int类型。
本题目也是一个经典的滑动窗口题目:
首先右边界不断扩展,去寻找匹配字符;
设置一个变量match,根据frequncy去统计s中和t匹配的字符个数;
当满足match已经可以等于t的串长时,可以收缩左边界
class Solution {
public String minWindow(String s, String t) {
if(s==null||t==null||s.length()==0||t.length()==0) return "";
int[] freq = new int[200];
//使用frequency 记录一个字符出现的次数
int left=0;
int right=0;
//substring初始为""
int start=0;
int end=0;
int match=0;//匹配的字符个数
int minlength = s.length()+1;
for (char c: t.toCharArray()){
freq[c]++;
}
while(right<s.length()){//right max = s.length-1{
char charRight = s.charAt(right);
freq[charRight]--;//表示对于t中已经匹配的字符,对应的frequency减少
//如果freq不为负数,则说明s中的某个字符也出现在t中
if(freq[charRight]>=0){
//匹配 match++
match++;
}
//为了保证substring包含右边界
right++;
//什么时候可以移动:如果存在已经匹配的子串时可以移动
//条件就是 match==t.length()
while(match==t.length()){
//当匹配长度等于t.length,记录此时的start和end,可以对左边界收缩
//后续循环继续根据match更新start和end
int size =right-left;
if(size<minlength){
minlength=size;
start=left;
end=right;
}
//如果移出了与t中可以匹配的字符
char charLeft = s.charAt(left);
//不在t中的,freq一直是0
freq[charLeft]++;
if(freq[charLeft]>0) //说明移出了已经可以匹配的字符
match--;
left++;
}
}
return s.substring(start,end);
}
}
网友评论