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);
    }
}
相关推荐
luj_17681 小时前
马克思的跨学科学术体系
c语言·开发语言·c++·经验分享·算法
阿文的代码库1 小时前
干货分享|C++运算符重载知识点
java·c++·算法
Deep-w1 小时前
【MATLAB】基于 MATLAB 的直流电动机双闭环调速系统建模与仿真
开发语言·算法·matlab
数幄科技1 小时前
电力装备制造业智能化转型】【数据基础设施篇】【5】数据采集 ETL 的可靠性设计
大数据·人工智能·算法·数据治理·数幄科技
AI科技星1 小时前
引电统一方程:严格推导与量纲零错误验证
人工智能·算法·机器学习·架构·学习方法
fengxin_rou2 小时前
leetcode二维数组高频面试题详解:48.原地旋转矩阵 + 240.杨氏矩阵查找算法深度剖析
数据结构·leetcode·java 算法·面试算法
8Qi82 小时前
LeetCode 518:零钱兑换 II(Coin Change II)—— 题解 ✅
java·算法·leetcode·动态规划·完全背包
计算机安禾2 小时前
【算法分析与设计】第49篇:算法博弈论与机制设计
人工智能·算法·机器学习
酉鬼女又兒2 小时前
零基础入门计算机网络数据链路层:从基本概念、封装成帧到差错检测核心原理全解析
服务器·网络·网络协议·tcp/ip·计算机网络·考研·职场和发展