76. 最小覆盖子串

76. 最小覆盖子串

题目描述

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 ≤ s . l e n g t h , t . l e n g t h ≤ 1 0 5 1 \le s.length, t.length \le 10^5 1s.length,t.length105
  • st 由英文字母组成

**进阶:**你能设计一个在 o(n) 时间内解决此问题的算法吗?


题解:

滑动窗口。

使用哈希表统计 t 中的每个字符出现个数,使用两个指针 lr 维护s 中一个包含 t 的子串左右边界,初值都为 0,表示窗口为空。

那么如何判断 s[l...r] 包含了 t 的所有字符呢?

可以使用一个计数器 cnt ,初值为 t 的长度,每次移动窗口右指针 r 时, 若哈希表中 s[r] 个数不为零 ,则计数器 cnt 减一。当 cnt 为零的时候,说明找到了一个子串。

注意:找到了一个子串,还需要移动左指针 l ,过滤掉无用的字符,只有当 lr 分别指向 t 中的字符,且它们的出现次数正好都为零,此时才是当前窗口的最优值。比如: s = "abbcd"t = "bcd",在 l = 0, r = 4 时,s[0..4] 包含 t 中所有字符,但是 s[0...1] 是多余的,应该跳过。

时间复杂度: O ( n ) O(n) O(n)

额外空间复杂度: O ( C ) O(C) O(C)C 指字符集大小

class Solution {
public:
    string minWindow(string s, string t) {
        int n = s.length();
        int m = t.length();
        if ( n < m ) return "";
        vector<int> hash(256);
        for ( auto& it : t )
            ++hash[it];
        int l = 0, r = 0, cnt = m;
        int min_len = n + 1, st = -1;
        for( r = 0; r < n; ++r ) {
            if ( --hash[s[r]] >= 0 ) --cnt;
            if ( cnt ) continue;
            while ( l < r && hash[s[l]] < 0 ) ++hash[s[l++]];
            if ( r - l + 1 < min_len ) {
                min_len = r - l + 1;
                st = l;
            }
            ++cnt, ++hash[s[l++]]; // 窗口左边界右移
        }
        if ( st == -1 ) return "";
        return s.substr( st, min_len );
    }
};
/*
时间:8ms,击败:95.27%
内存:7.6MB,击败:92.83%
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值