题目描述:
给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入:S = "ADOBECODEBANC", T = "ABC"
输出:"BANC"
提示:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
相似题目
日志统计
思路:
1.设left为窗口左边界,right为窗口右边界;
2.我们得找到第一次包含全部目标字符串时,left和
right的位置,不断l++不断缩小窗口的大小,当l变
大时,看此时窗口内所包含的子串是否存在T,如果存
在更新最小值,不存则右边界right继续扩大,并重复
上述步骤;
3.怎么判断left~right之间是否包含T呢?用两个数组
target[]用来记录T中的个个字符出现的次数,
map[]用来记录当left~right中的个个字符出现的次数
并用count来记录是否T中所有的字符都已全部包含;
4.当s.charAt(r),存在于T中且出现次数小于等于
target[s.charAt(r)]时count++,为了避免字符重复出现
当count==T.length()时
则说明T中所有的字符都已被包含,开始缩小窗口;
5.缩小窗口的时候判断此时窗口是否还包含的T的方法一样
s.charAt(l)存在于T且target[s.charAt(l)]>=
map[s.charAt(l)]时,count--;
*说的很乱需要在草稿纸上画一下,我也想讲清楚实力不允许啊 *
代码:
class Solution {
public String minWindow(String s, String t) {
if (s == null || s == "" || t == null || t == "" || s.length() < t.length()) {
return "";
}
int length=s.length();
int map[]=new int[128];
//int map[]=new int [l28];
int target[]=new int[128];
for(int i=0;i<t.length();i++){
target[t.charAt(i)]++;
}
int left=0;
int right=0;
int count=0;
int anslength=99999;
String ans="";
while(right<s.length()){
//找到一个区间包含t
char temp=s.charAt(right);
map[temp]++;
//count=t.length()的时候说明全部找到
//首先这个字母得在t里存在,其次存在的次数不得超过t里的次数
if(target[temp]>0&&target[temp]>=map[temp]){
count++;
}
//找完了,就缩小左边界
while(count==t.length()){
char temp2=s.charAt(left);
//看这个字符是否存在,其次存在的次数如果开始小于等于t里
//的时候就要开始注意了不能再减了,举个例子C此时窗口里
//BBAC 而T=BAC,则此时的map[B]=2,target[B]=1,可以减一次
if(target[temp2]>0&&target[temp2]>=map[temp2])
count--;
if(right-left+1<anslength){
anslength=right-left+1;
ans = s.substring(left, right + 1);
// res=s.substring(left,right+1);
}
map[temp2]--;
left++;
}
right++;
}
return ans;
}
}