力扣热门100题之最小覆盖子串

核心解法:滑动窗口 + 哈希表

思路(4 步走)

  1. 用数组 / 哈希表统计 t 中字符的出现次数

  2. 用左右指针形成滑动窗口

  3. 右指针一直右移,直到窗口包含 t 所有字符

  4. 满足条件后,左指针尽量右移,缩小窗口,记录最小窗口

  5. 两个计数数组

  • 用数组比 HashMap 更快
  • 128 覆盖所有 ASCII 字符
java 复制代码
int[] need[128];   // 记录 t 里每个字符需要多少个
int[] window[128]; // 记录当前窗口里每个字符有多少个
  1. 统计 t 字符数量

比如 t="ABC"need 'A'=1, need 'B'=1, need 'C'=1

java 复制代码
for (char c : t.toCharArray()) need[c]++;
  1. 右指针扩张窗口
  • 右指针一直走
  • 遇到 t 需要的字符,就加入窗口
  • 当窗口字符数 = 需要的数量 时,valid++
java 复制代码
while (valid == t.length()) {
    更新最小窗口
    左指针右移
    如果移出的是需要的字符,可能导致 valid--
}
  1. 左指针收缩窗口(最关键)
  • valid == t.length() → 窗口已经包含 t 所有字符
  • 这时尽量移动左指针缩小窗口,寻找更短的满足条件的窗口
java 复制代码
while (valid == t.length()) {
    更新最小窗口
    左指针右移
    如果移出的是需要的字符,可能导致 valid--
}
  1. 最后返回结果
java 复制代码
return minLen == 无穷大 ? "" : s.substring(start, start+minLen)

核心变量总结

need[]:t 需要的字符数量

window[]:当前窗口字符数量

valid:窗口中已经满足数量要求的字符种类数

valid == t.length() → 窗口满足条件

完整代码实现:

java 复制代码
class Solution {
    public String minWindow(String s, String t) {
        // 用于统计字符串 t 中每个字符需要出现的次数
        int[] need = new int[128];
        // 用于统计当前滑动窗口内,各字符的数量
        int[] window = new int[128];

        // 记录 t 中有多少种【不同的字符】(比如 t="aa" → 只有1种)
        int needUnique = 0;

        // 第一步:统计 t 中所有字符的需求
        for (char c : t.toCharArray()) {
            // 第一次遇到这个字符,才增加种类数
            if (need[c] == 0) {
                needUnique++;
            }
            need[c]++;
        }

        // 滑动窗口左右指针
        int left = 0, right = 0;
        // 记录窗口内已经满足数量要求的【字符种类数】
        int valid = 0;

        // 记录最小窗口的起始位置和长度
        int start = 0;
        int minLen = Integer.MAX_VALUE;

        // 第二步:移动右指针,扩展窗口
        while (right < s.length()) {
            // 当前要加入窗口的字符
            char c = s.charAt(right);
            right++;

            // 如果这个字符是 t 中需要的字符
            if (need[c] > 0) {
                // 窗口中该字符数量 +1
                window[c]++;

                // 如果当前字符的数量【刚好达到需求】
                // 说明这一种字符凑齐了,valid +1
                if (window[c] == need[c]) {
                    valid++;
                }
            }

            // 第三步:当窗口满足条件时(所有字符种类都凑齐了)
            // 开始移动左指针,缩小窗口,寻找更短的子串
            while (valid == needUnique) {
                // 更新最小窗口:如果当前窗口更小,就记录下来
                if (right - left < minLen) {
                    start = left;
                    minLen = right - left;
                }

                // 要移出窗口的字符
                char d = s.charAt(left);
                left++;

                // 如果移出的字符是 t 中需要的字符
                if (need[d] > 0) {
                    // 如果移出前,该字符数量刚好满足需求
                    // 那么移出后就不满足了 → valid -1
                    if (window[d] == need[d]) {
                        valid--;
                    }
                    // 窗口中该字符数量 -1(真正移出)
                    window[d]--;
                }
            }
        }

        // 最后:如果没有找到合法窗口,返回空字符串
        // 否则返回最小窗口子串
        return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
    }
}
相关推荐
就叫年华吧丶8 分钟前
长文档点目录定位总是不准?一个 content-visibility + 平滑滚动引发的连环坑(Vue3 实战)
前端·javascript·算法·vue
FPGA信号处理15 分钟前
【信号检测与估计】第四节课:非高斯噪声下的 BLUE、极大似然与 EM 算法
人工智能·算法·机器学习
.道阻且长.41 分钟前
C++ 11:可变参数模板
前端·c++·算法
Doubbbbbbble云3 小时前
基于贪心算法的区间覆盖问题求解策略4
算法·贪心算法
不会就选b9 小时前
算法日常・每日刷题--<贪心>25
数据结构·算法
Cccp.12313 小时前
【leetcode】(七)前缀树和贪心算法
数据结构·leetcode·贪心算法
千里码aicood13 小时前
基于CART算法的图书分类系统设计与实现
数据库·算法·分类
做cv的小昊13 小时前
【World Model】π0.5:a Vision-Language-Action Model with Open-World Generalization
人工智能·算法·机器学习·大模型·多模态·vla·世界模型
لا معنى له14 小时前
World-In-World: World Models in a Closed-Loop World
算法