问题描述(原题链接)
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
代码:
第一个版本(超出时间限制)
class Solution {
public String minWindow(String s, String t) {
int len1 = s.length();
int len2 = t.length();
//滑动窗口
int left =0;
int right=0;
int res=Integer.MAX_VALUE;
int lindex=0;
int rindex=0;
HashMap<Character,Integer> map1 = new HashMap<Character,Integer>();
for(int i=0;i<=len1;){
if(test(map1,t)){ //包含这个字串
while(test(map1,t) && left<=right){
map1.put(s.charAt(left),map1.get(s.charAt(left))-1);
left++;
}
if(res>right-left+1){
res=right-left+1;
lindex=left-1;
rindex=right-1;
}
}else{
while(!test(map1,t) && right<len1){
map1.put(s.charAt(right),map1.getOrDefault(s.charAt(right),0)+1);
right++;
i++;
}
}
}
return s.substring(lindex,rindex+1);
}
public boolean test(HashMap<Character,Integer> map,String t){//检查是否包含字串
for(int i=0;i<t.length();i++)
if(map.getOrDefault(t.charAt(i),0)<1)
return false;
return true;
}
}
第二个版本(某大佬的:题解)
class Solution1 {
public String minWindow(String s, String t) {
//维护s串中滑动窗口中各个字符出现次数
Map<Character, Integer> hs = new HashMap<>();
//维护t串中各个字符出现次数
Map<Character, Integer> ht = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
ht.put(t.charAt(i), ht.getOrDefault(t.charAt(i), 0)+1);
}
String ans="";
//cnt维护s串[left,right]中满足t串的元素的个数,记录相对应字符的总数
int len=Integer.MAX_VALUE,cnt=0;
//区间[left,right]表示当前滑动窗口
for (int left=0,right = 0; right < s.length(); right++) {
hs.put(s.charAt(right), hs.getOrDefault(s.charAt(right), 0)+1);
//如果ht表中也包含当前字符
if (ht.containsKey(s.charAt(right))) {
//并且hs表中的字符个数<=ht表中的字符个数,说明该字符是必须的,并且还未到达字符串t所要求的数量
if (hs.get(s.charAt(right))<=ht.get(s.charAt(right))) {
cnt++;
}
}
//收缩滑动窗口
//如果左边界的值不在ht表中 或者 它在hs表中的出现次数多于ht表中的出现次数
while(left < right && (!ht.containsKey(s.charAt(left)) || hs.get(s.charAt(left)) > ht.get(s.charAt(left)))){
hs.put(s.charAt(left),hs.get(s.charAt(left)) - 1);
left++;
}
//此时滑动窗口包含符串 t 的全部字符
if (cnt==t.length()&&right-left+1<len) {
len=right-left+1;
ans=s.substring(left,right+1);
}
}
return ans;
}
}