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);
    }
}
相关推荐
问商十三载10 小时前
2026大模型GEO内链优化:3个传导逻辑提权重,零成本提29%收录优先级附布局表
人工智能·算法
Risk Actuary11 小时前
手动示例解释机器学习中 GBDT 算法原理
人工智能·算法·机器学习
血色橄榄枝17 小时前
基于用户注册信息的关键词检测挑战赛「Datawhale AI 夏令营」
人工智能·算法·机器学习
c2385618 小时前
第二篇:《测试指挥官:可视化单题自测框架(含 assert 实操)》
java·数据库·c++·算法·安全性测试
六点_dn19 小时前
Linux学习笔记-printf命令
linux·运维·算法
遥感知识服务20 小时前
Sentinel-1 + DEM + FwDET + 随机森林:从快速水深初估到多因子误差修正
算法·随机森林·sentinel
来一碗刘肉面20 小时前
顺序表与链表的比较
数据结构·算法·链表
alphaTao20 小时前
LeetCode 每日一题 2026/7/13-2026/7/19
算法·leetcode
nnerddboy21 小时前
脑电信号处理实战 03 | 运动想象脑机接口入门:ERD/ERS、CSP 空间滤波与左右拳想象解码
算法·信号处理
QN1幻化引擎1 天前
Dalin L — 我造了一门支持中文编程的语言,完整移植到 Rust 了
人工智能·算法·机器学习