leetcode 76. 最小覆盖子串

题目叙述

给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入:S = “ADOBECODEBANC”, T = “ABC”
输出:“BANC”
提示:
如果 S 中不存这样的子串,则返回空字符串 “”。
如果 S 中存在这样的子串,我们保证它是唯一的答案。

分析

本题属于典型的滑动窗口的题目,滑动窗口的核心在于:

  • 遍历求解连续的子字符串的问题
  • 对时间复杂度有一定的高效率
  • 设定左指针和右指针
  • 什么时候更新左指针什么时候更新右指针,本处主要当满足条件的时候,不断收缩窗口,即不断右移动左指针,并且有可能一直符合条件,所以要把该条件判断放在一个while循环中。当不满足条件的时候就要正常地右移动指针。

滑动窗口的步骤如下:

  • 确定左右指针的初始值(左指针的意义是当前的窗口的左边界,右指针的意义就是当前的窗口的右边界,因此当前的窗口的长度为r-l+1)。
  • 一般是二层循环,但是时间复杂度一般都是O(n)。

代码的模板为:

string minWindow(string s, string t) {
        int l = ;
        int r = ;
        while(r < int(s.size())){
            //处理逻辑
            r++;
            while(check()){
            	...
                ++l;
            }  
            
        }
        return ;
    }

代码

注意此处的 while(check())前面的逻辑只能放在上面,否则以s.size()-1结尾的字符串就无法被处理。

class Solution {
public:
    unordered_map <char, int> ori, cnt;
    bool check() {
        for (const auto &p: ori) {
            if (cnt[p.first] < p.second) {
                return false;
            }
        }
        return true;
    }
    string minWindow(string s, string t) {
        string ans = "";
        for(const auto &c: t){
            ++ori[c];
        }
        int l = 0, r = -1;
        int len = INT_MAX;
        while(r < int(s.size())){
            // if(ori.find(s[++r]) != ori.end()){
            //    ++cnt[s[++r]];          
            // }
            ++cnt[s[++r]];//此处要先进行++,不能使用s[r++],因为我们指定r为当前的字符串的结尾的而不是子字符串的下一个位置,由于要先++,所以r的初始值要初始化为-1而不是0
            while(check()){
                if(r - l + 1 < len){
                    len = r - l + 1;
                    ans = s.substr(l, len);
                }
                // if(ori.find(s[l]) != ori.end()){//ori对应的是t, 如果当前的左指针的位置元素在ori中,其实也可以不用判断
                --cnt[s[l]];
                ++l;
            }  
            
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值