/* * 滑动窗口算法框架 */ voidslidingWindow(String s, String t){ Map<Character, Integer> need = new HashMap<>(); Map<Character, Integer> window = new HashMap<>();
// 左闭又开 int left = 0, right = 0; // 计数 int valid = 0; // 记录字符串 t for (int i = 0; i < t.length(); i++) { need.put(t.charAt(i), need.getOrDefault(t.charAt(i), 0) + 1); }
while(right < s.length()) { // c 是将移入窗口的字符 char c = s.charAt(right); // 增大窗口 right++; // 进行窗口内数据的一系列更新 ...
public String minWindow(String s, String t){ // 计数,记录t Map<Character, Integer> need = new HashMap<>(); // 计数,记录s Map<Character, Integer> window = new HashMap<>();
// 左闭又开 int left = 0; int right = 0; // 计数 int valid = 0; // 记录最小子串的起始位置和长度 int start = 0; int len = Integer.MAX_VALUE; // 记录字符串 t for (int i = 0; i < t.length(); i++) { need.put(t.charAt(i), need.getOrDefault(t.charAt(i), 0) + 1); }
while (right < s.length()) { char c = s.charAt(right); // 扩大窗口 right++; // 窗口内数据更新 if (need.containsKey(c)) { window.put(c, window.getOrDefault(c, 0) + 1); if (window.get(c).equals(need.get(c))) { valid++; } } // 判断左侧窗口是否收缩 while (valid == need.size()) { // 更新最小覆盖子串 if (right - left < len) { // 更新起始位置和长度 start = left; len = right - left; } // d 是移除窗口的元素 char d = s.charAt(left); left++; // 更新 if (need.containsKey(d)) { if (window.get(d).equals(need.get(d))) { valid--; } window.put(d, window.get(d) - 1); } } } return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len); }
2. 字符串排列
这个题目是明显的滑动窗口算法,问题可以转换为:给你字符串 s 和 t,请问 s 中是否存在一个子串,包含 t 中所有字符且不包含其他字符(排列)。
public List<Integer> findAnagrams(String s, String p){ Map<Character, Integer> need = new HashMap<>(); Map<Character, Integer> window = new HashMap<>();
for (int i = 0; i < p.length(); i++) { need.put(p.charAt(i), need.getOrDefault(p.charAt(i), 0) + 1); }
int left = 0, right = 0; int valid = 0; // 存结果 List<Integer> res = new ArrayList<>();
while (right < s.length()) { char c = s.charAt(right); right++;
// 更新数据 if (need.containsKey(c)) { window.put(c, window.getOrDefault(c, 0) + 1); if (window.get(c).equals(need.get(c))) { valid++; } }
// 收缩 while (right - left >= p.length()) { if (valid == need.size()) { res.add(left); } char d = s.charAt(left); left++; // 更新 if (need.containsKey(d)) { if(window.get(d).equals(need.get(d))) { valid--; } window.put(d, window.get(d) - 1); } } } return res; }