力扣-76.最小覆盖子串
题目链接
76.最小覆盖子串
class Solution {public String minWindow(String s, String t) {// 统计目标字符串t中各字符的出现次数HashMap<Character, Integer> target = new HashMap<>();for (int i = 0; i < t.length(); i++) {target.put(t.charAt(i), target.getOrDefault(t.charAt(i), 0) + 1);}int left = 0;int right = 0;int len = Integer.MAX_VALUE;int valid = 0; // 已匹配的有效字符数int start = 0; // 最小窗口的起始位置,方便返回结果时直接取子串while (right < s.length()) {// 右指针不断右移扩展窗口char r = s.charAt(right);if (target.containsKey(r)) {target.put(r, target.get(r) - 1);if (target.get(r) >= 0) {valid++;}}// 当所有字符都匹配时,尝试左移左指针以缩小窗口while (valid == t.length()) {// 注意更新时机if (right - left + 1 < len) {len = right - left + 1;start = left;}char l = s.charAt(left);if (target.containsKey(l)) {target.put(l, target.get(l) + 1);if (target.get(l) > 0) {valid--;}}left++;}right++;}return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);}
}
小结:主要分为以下几个步骤:
- 初始化阶段:
- 使用
HashMap
统计目标字符串t
中每个字符的出现频率 - 初始化滑动窗口的左右指针、最小窗口长度等变量
- 滑动窗口主循环:
- 右指针不断右移扩展窗口
- 每当遇到
t
中的字符时,减少其需求计数 - 当
valid
等于t
长度时,表示当前窗口包含所有所需字符
- 窗口收缩阶段:
- 尝试左移左指针以缩小窗口
- 只有当窗口变小且仍满足条件时才更新最小窗口记录
- 移除左边界的字符时,恢复其需求计数
- 结果处理:
- 如果没有找到符合条件的窗口,返回空字符串
- 否则返回从
start
开始、长度为len
的子串