分析
思路:
1、利用双指针left和right维持一个窗口,起始left=right=0;
2、右指针不断右移,直到所有的所有的字符都被包含在这个窗口内
3、此时移动左指针,直到恰好有一个字符没有被包含在窗口内,在移动的过程中更新最小间距,并记录最短子串的开始位置
4、继续重复2,3步骤,直到右指针到达字符串末尾
代码:
import java.util.*;
public class Solution {
/**
*
* @param S string字符串
* @param T string字符串
* @return string字符串
*/
public String minWindow (String S, String T) {
//保存T中字符的个数
Map<Character,Integer> map = new HashMap<>();
for(int i = 0; i < T.length(); i++) {
map.getOrDefault(T.charAt(i),0);
map.put(T.charAt(i),map.getOrDefault(T.charAt(i),0) + 1);
}
//左指针
int begin = 0;
//右指针
int end = 0;
//包含所有字符的间距
int d = Integer.MAX_VALUE;
//记录最短子串的开始位置
int pre = 0;
//记录有多少字符被包含到窗口内
int counter = T.length();
//遍历字符串S
while (end < S.length()) {
Integer num = map.get(S.charAt(end));
//如果字符在T中
if(num != null) {
//同一个字符在窗口内可能多次出现,但是这些字符只能算一次
if(num > 0) {
counter--;
}
map.put(S.charAt(end),num-1);
}
//如果包含所有的字符的窗口
while (counter == 0 && begin <= end) {
if(end - begin < d) {
d = end - begin + 1;
pre = begin;
}
//向前移动字符串
Integer num2 = map.get(S.charAt(begin));
if(num2 != null) {
//如果map中保存的所有字符的出现次数小于等于0,说明其还存在最小间距
if(num2 == 0) {
counter++;
}
map.put(S.charAt(begin),num2 + 1);
}
begin++;
}
end++;
}
return d == Integer.MAX_VALUE ? "":S.substring(pre,pre + d);
}
}