力扣热门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);
    }
}
相关推荐
小雨下雨的雨43 分钟前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
xieliyu.3 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
一条小锦吕*4 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
如竟没有火炬5 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
8Qi86 小时前
LeetCode 1143 & 718:最长公共子序列 / 最长重复子数组
算法·leetcode·职场和发展·动态规划
绿算技术6 小时前
万卡推理集群存储选型分析:从核心架构到应用视角
大数据·科技·算法·架构
想吃火锅10057 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
net3m338 小时前
一阶软件低通滤波器算法
人工智能·算法
水木流年追梦8 小时前
大模型入门-大模型优化方法12-YaRN 长文本外推技术
人工智能·分布式·算法·正则表达式·prompt