一、滑動窗口題型模板
/* * 滑動窗口類型: 模板 */ public List<Integer> slideWindowMode(String s, String t) { // 1 根據題目返回類型定義數據結構 ArrayList<Integer> result = new ArrayList<>(); if(t.length()> s.length()) return result; // 2 新建Map, Key=字符,value=頻率 HashMap<Character, Integer> map = new HashMap<>(); for(char c: t.toCharArray()) map.put(c, map.getOrDefault(c, 0) + 1); // 3 定義變量 int counter = map.size(); // 目標字符串中的不同字符種類 int begin = 0, end = 0; // 窗口起始、結束點 int len = Integer.MAX_VALUE; // 4 源字符串開始遍歷 while(end < s.length()) { // 5 統計每個字符 char c = s.charAt(end); if(map.containsKey(c)) { map.put(c, map.get(c) - 1); if(map.get(c) == 0) counter--; } end++; // 6 符合情況!begin~end 之間包含 t 的所有字符 while(counter == 0) { // 此時 Map 的 value 全部 <= 0 char tmpc = s.charAt(begin); if(map.containsKey(tmpc)) { map.put(tmpc, map.get(tmpc) + 1); if(map.get(tmpc) > 0) counter++; } // 7 do sth begin++; } } // 8 return result; }
二、LeetCode 中 幾個滑動窗口套用模板實現
1、 76. Minimum Window Substring
https://leetcode.com/problems/minimum-window-substring/description/
public String minWindow(String s, String t) { if(t.length()> s.length()) return ""; HashMap<Character, Integer> map = new HashMap<>(); for(char c: t.toCharArray()) map.put(c, map.getOrDefault(c, 0) + 1); int counter = map.size(); // 目標字符串中的不同字符種類 int begin = 0, end = 0; // 窗口起始、結束點 int len = Integer.MAX_VALUE; int head = 0; while(end < s.length()) { char c = s.charAt(end); if( map.containsKey(c) ) { map.put(c, map.get(c) - 1); if(map.get(c) == 0) counter--; } end++; while(counter == 0) { // 此時 Map 的 value 全部 <= 0 char tmpc = s.charAt(begin); if( map.containsKey(tmpc) ) { map.put(tmpc, map.get(tmpc) + 1); if(map.get(tmpc) > 0) counter++; } //---------- if(end - begin < len) { len = end - begin; head = begin; } //---------- begin++; } } if(len == Integer.MAX_VALUE ) return ""; return s.substring(head, head + len); }
2、3 Longest Substring Without Repeating Characters
https://leetcode.com/problems/longest-substring-without-repeating-characters/description/
/* * 2、 Longest Substring Without Repeating Characters */ public int lengthOfLongestSubstring(String s) { HashMap<Character, Integer> map = new HashMap<>(); int begin = 0; // 窗口起始、結束點 int max = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if(map.containsKey(c)) { max = Math.max(max, i - begin); begin = Math.max(begin, map.get(c) + 1); map.put(c, i); } else { map.put(c, i); } } max = Math.max(s.length() - begin, max); return max; }
3、438. Find All Anagrams in a String
https://leetcode.com/problems/find-all-anagrams-in-a-string/description/
public List<Integer> findAnagrams(String s, String t) { ArrayList<Integer> result = new ArrayList<>(); if(s.length() < t.length()) return result; HashMap<Character, Integer> map = new HashMap<>(); for(char c: t.toCharArray()) map.put(c, map.getOrDefault(c, 0) + 1); int counter = map.size(); int begin = 0, end = 0; // int head = 0; // int len = Integer.MAX_VALUE; while(end < s.length()) { char c = s.charAt(end); if( map.containsKey(c) ) { map.put(c, map.get(c) - 1); if(map.get(c) == 0) counter--; } end++; while(counter == 0) { char tmpc = s.charAt(begin); if( map.containsKey(tmpc) ) { map.put(tmpc, map.get(tmpc) + 1); if(map.get(tmpc) > 0) counter++; } //-------- if(end - begin == t.length()) result.add(begin); //-------- begin++; } } return result; }