滑動窗口
:定義一個hashMap
存放字符串T
中的所有元素,窗口框定S
字符串,left---right
確定當前所確定的元素,若在left-----right
範圍內不包含T
則將right
不斷向右移動,若符合,則再將left
向右移動直到不包含該T
,用T
中的map
的每個值是否爲0即可判斷是否包含T
/**
* 重點分析
* @param
* ,並且不要求順序,之前已經用過很多次了,利用 HashMap,
* 對於兩個字符串 S = "ADOBECODEBANC", T = "ABCB",
* 用 map 統計 T 的每個字母的出現次數,然後遍歷 S,遇到相應的字母,就將相應字母的次數減 1,
* 如果此時 map 中所有字母的次數都小於等於 0,那麼此時的窗口一定包含了所有字母。
*/
public String minWindow2(String s, String t) {
Map<Character, Integer> map = new HashMap<>();
//遍歷字符串 t,初始化每個字母的次數
for (int i = 0; i < t.length(); i++) {
char char_i = t.charAt(i);
map.put(char_i, map.getOrDefault(char_i, 0) + 1);
}
int left = 0; //左指針
int right = 0; //右指針
int ans_left = 0; //保存最小窗口的左邊界
int ans_right = -1; //保存最小窗口的右邊界
int ans_len = Integer.MAX_VALUE; //當前最小窗口的長度
//遍歷字符串 s
while (right < s.length()) {
char char_right = s.charAt(right);
//判斷 map 中是否含有當前字母
if (map.containsKey(char_right)) {
//當前的字母次數減一
map.put(char_right, map.get(char_right) - 1);
//開始移動左指針,減小窗口(滿足map中的值一直爲空的話)
while (match(map)) { //如果當前窗口包含所有字母,就進入循環
//當前窗口大小
int temp_len = right - left + 1;
//如果當前窗口更小,則更新相應變量
if (temp_len < ans_len) {
ans_left = left;
ans_right = right;
ans_len = temp_len;
}
//得到左指針的字母
char key = s.charAt(left);
//判斷 map 中是否有當前字母
if (map.containsKey(key)) {
//因爲要把當前字母移除,所有相應次數要加 1
map.put(key, map.get(key) + 1);
}
left++; //左指針右移
}
}
//右指針右移擴大窗口
right++;
}
return s.substring(ans_left, ans_right+1);
}
//判斷所有的 value 是否爲 0
private boolean match(Map<Character, Integer> map) {
for (Integer value : map.values()) {
if (value > 0) {
return false;
}
}
return true;
}