76. 最小覆盖子串

本文介绍了一种使用滑动窗口算法解决在字符串s中找到涵盖字符串t所有字符的最小子串的方法。通过维护一个窗口,并动态调整左右边界,确保窗口内字符满足目标字符串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 的子串中,
因此没有符合条件的子字符串,返回空字符串。

思路

在这道题中, 我们采用滑动窗口的思路来解题.

初始化 [left, right)的窗口window, 不断增加 right指针 扩大窗口范围, 直至窗口中的元素满足要求.
此时, 我们停止增大 right指针, 转而增大 left指针 来不断缩小窗口范围, 直至窗口中的元素不再满足要求, 每增加一次 left指针, 我们便要更新一轮结果.
重复以上思路, 直至 right 到达字符串尽头.

我们采用 need 来记录目标字符串中字符出现的次数, 使用 valid 来记录 window 中满足 need 条件的字符个数, 如果 valid等于need.size(), 开始收缩窗口范围.

代码

class Solution {
public:
    string minWindow(string s, string t) {
        map<char, int> need, window;
        for (char c : t) {
            need[c]++;
        }

        int valid = 0;
        int left = 0, right = 0;
        int start = 0, length = INT_MAX;

        while (right < s.length()) {
            char c = s[right];
            right++;
            /*
            	在这里有一个问题: 
                	当 key = c 时, 那他对应的 value 应该是大于等于 1 的;
                    但是 need[c] >= 1 的判定条件无法求的结果, 只能使用
                    need.find(c) != need.end() 或 need.count(c)
                
                解决:
                	如果使用 need[c] >= 1, 当 c 不存在的时候, 
                    need 会在创建一个新的索引, 导致 need.size() 越来越大
            */
            if (need.find(c) != need.end()) {
                window[c]++;
                if (window[c] == need[c])
                    valid++;
            }
            while (valid == need.size()) {

                if (right - left < length) {
                    start = left;
                    length = right - left;
                }
                char ch = s[left];
                left++;
                if (need.find(ch) != need.end()) {
                    if (window[ch] == need[ch])
                        valid--;
                    window[ch]--;
                }
            }
        }
        return length == INT_MAX ? "" : s.substr(start, length);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值