16.滑动窗口经典例题:最小覆盖子串(LeetCode 76)算法原理剖析

目录

一、题目解析

二、讲解算法原理

[解法一:暴力枚举 + 哈希表](#解法一:暴力枚举 + 哈希表)

[解法二:滑动窗口 + 哈希表](#解法二:滑动窗口 + 哈希表)

优化:判断条件

三、代码实现


大家好,今天我们来攻克 LeetCode 上的一道经典难题------76. 最小覆盖子串。这道题是滑动窗口算法的典型应用,结合了哈希表来优化判断过程。


一、题目解析

题目: ​ 给你一个字符串 s、一个字符串 t。返回 s中涵盖 t所有字符的最小子串。如果 s中不存在涵盖 t所有字符的子串,则返回空字符串 ""

注意:

  1. 对于 t中重复字符,我们寻找的子串中该字符数量必须不少于 t中该字符数量。

  2. 如果 s中存在这样的子串,我们保证它是唯一的答案。

示例 1:

  • 输入:s = "ADOBECODEBANC", t = "ABC"

  • 输出:"BANC"

  • 解释: ​ 最小覆盖子串 "BANC"包含来自字符串 t'A''B''C'

示例 2:

  • 输入:s = "a", t = "a"

  • 输出:"a"

  • 解释: ​ 整个字符串 s是最小覆盖子串。

示例 3:

  • 输入:s = "a", t = "aa"

  • 输出:""

  • 解释:t中两个字符 'a'均应包含在 s的子串中,因此没有符合条件的子子串,返回空字符串。


二、讲解算法原理

解法一:暴力枚举 + 哈希表

解法二:滑动窗口 + 哈希表

这是本题的最优解。核心思想是维护一个窗口 [left, right],通过移动左右指针来寻找最小覆盖子串。

  • 核心逻辑:

    1. right 右移: ​ 不断扩大窗口,直到窗口包含了 t中的所有字符。

    2. **left 右移:**​ 在满足覆盖条件的前提下,尝试缩小窗口左边界,以找到最小长度。

优化:判断条件

为了优化每次判断窗口是否覆盖 t的时间复杂度,我们可以引入一个变量 count

  • 思路: ​ 使用变量 count标记有效字符的种类。

    • 进窗口: ​ 当 hash2[in] == hash1[in]时,count++

    • 出窗口: ​ 当 hash2[out] == hash1[out]时,count--

    • 判断条件: ​ 当 count == hash1.size()时,说明窗口已覆盖 t


三、代码实现

java 复制代码
class Solution 
{
    public String minWindow(String ss, String tt) 
    {
        char[] s = ss.toCharArray();
        char[] t = tt.toCharArray();

        int[] hash1 = new int[128]; // 统计字符串 t 中字符的频次
        int kinds = 0; // 字符串 t 中,有多少种字符
        for(char ch : t)
        {
            if(hash1[ch]++ == 0) kinds++;
        }

        int[] hash2 = new int[128]; // 统计窗口中字符的频次

        int minlen = Integer.MAX_VALUE, begin = -1;
        for(int left = 0, right = 0, count = 0; right < s.length; right++)
        {
            char in = s[right];
            if(++hash2[in] == hash1[in]) count++; // 进窗口 + 维护 count
            
            while(kinds == count) // 判断
            {
                // 更新结果
                if(right - left + 1 < minlen)
                {
                    begin = left;
                    minlen = right - left + 1;
                }
                
                char out = s[left++];
                if(hash2[out]-- == hash1[out]) count--; // 出窗口 + 维护 count
            }
        }
        
        if(begin == -1) return new String();
        else return ss.substring(begin, begin + minlen);
    }
}
相关推荐
To_OC26 分钟前
LC 128 最长连续序列:别上来就排序,O (n) 解法才是这题的灵魂
javascript·算法·leetcode
05Kevin14 小时前
lk每日冒险题--数据结构6.27
算法
To_OC1 天前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
千纸鹤安安1 天前
千问Qwen-AgentWorld来了:一个语言模型搞定七大Agent场景,GPT-5.4都输了
算法
七牛开发者1 天前
MCP 到底是什么?为什么 Agent 都想接上它
算法·aigc·agent
kisshyshy2 天前
从递归到迭代,一文吃透二叉树的核心知识与 JavaScript 实现
javascript·算法·代码规范
To_OC2 天前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode