76.最小覆盖子串

该博客介绍了如何使用滑动窗口方法来解决字符串子串覆盖问题。通过一个具体的例子展示了如何在给定字符串`s`中找到涵盖字符串`t`所有字符的最小子串。算法涉及在窗口扩大和缩小时如何维护有效状态,并在找到符合条件的子串时更新答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
 

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:

输入:s = "a", t = "a"
输出:"a"
示例 3:

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

使用滑动窗口方法(变长的滑动窗口)

采用了labuladongd的方法:

https://labuladong.gitee.io/algo/1/12/

class Solution 
{
public:
    string minWindow(string s, string t) 
    {
        unordered_map<char, int> need, window;//哈希表need和window,以键值方式存储每个字符出现的次数
        for (char c : t) //初始化need
        need[c]++;
        int left = 0, right = 0;
        int valid = 0;
        int start = 0, len = INT_MAX; //记录最小覆盖子串的起始位置及长度
        while (right < s.size()) //判断右侧窗口是否需要扩展
        {
            char c = s[right];
            right++;
            if (need.count(c)) 
            {
                window[c]++;
                if (window[c] == need[c])
                valid++;
            }

            while (valid == need.size()) //判断左侧窗口是否需要收缩
            {
                if (right - left < len) //更新最小覆盖字串
                {
                    start = left;
                    len = right - left;
                }

                char d = s[left];
                left++;
                if (need.count(d)) 
                {
                    if (window[d] == need[d])
                    valid--;
                    window[d]--;
                }                    
            }
        }
    return len == INT_MAX ?"" : s.substr(start, len);//返回最小覆盖子串
    }
};

思路:

1、初始化 left=right=0,把索引左闭右开区间 [left, right) 称为一个「窗口」。 

2、我们先不断地增加 right 指针扩大窗口 [left, right),直到窗口中的字符串符合要求(包含了 T 中的所有字符)。

3、此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 [left, right),直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。

4、重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。

滑动窗口题目需要考虑三点:

1、什么时候应该扩大窗口?

2、什么时候应该缩小窗口?

3、什么时候得到一个合法的答案?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值