leetcode刷题之76.最小覆盖子串

题目

给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
tag:Sliding window
diffculty:Hard

示例
输入:S = “ADOBECODEBANC”, T = “ABC”
输出:“BANC”

难点

  1. 如何确定这些元素都在win当中?
  2. 如何去缩减这些元素?

最开始的思路【弃】

使用一个hash表来存储这些旧元素的位置,然后如果这些元素都有位置了,表面当前window里面都存在这些元素,然后在移动的时候就维护这个hash表,找到他们之间最小的那个差。
最后这个思路我也就想想,其实我觉得这个思路不太清晰,于是还是去借鉴了人家大佬的思路,真的是又清晰又简单,完美的逻辑。

大佬的思路【√】

大佬的解答点这里

  1. 使用一个need数组来记录当前windows都有哪些字符,need的意思就是window里面需要得到的字符,如果不是必须的字符初始的值就是0
  2. 使用变量count来标记当前还有多少个元素没在win当中
  3. 当count为0的时候,将窗口做缩减操作,判断如果need中该元素需要小于0,就说明该元素不是必须的可以被移出window外部,直到遇到必须的元素这时就可以获得当前的window的局部最优解,在这个情况下就可以对当前结果做判断,如果小于历史的最小长度,就更新一下。

大佬的图片被我拷贝一下

cpp版本的代码

class Solution {
public:
    string minWindow(string s, string t) {
        if (s.size() < t.size() || s.size() < 1 || t.size() < 1) return "";
        int left = 0;
        int right = 0;
        //使用need数组来记录当前窗口所需要的元素的个数
        //当滑动窗口内包含一个元素就将它的值减一,如果移出一个元素就加一
        int  start = 0 , size = INT_MAX;
        
        vector<int> need(128,0);
        //先初始化need数组,将目标放进去
        for (int c : t) {
            need[c] ++;
        }
        //再设置一个num用来记录还有几个元素没被满足
        int count = t.size();
        while (right < s.size()) {
            int c = s[right];
            if (need[c] > 0 ) {
                count --;
            }
            need[c] -- ;
            //窗口此时符合要求
            if(count == 0) {
                //left此时应该开始移动缩减窗口
                while (left < right && need[s[left]] < 0) {
                    need[s[left]] ++;
                    left ++;
                }
                //更新一下size
                if(size > right - left + 1) {
                    start = left;
                    size = right - left + 1;
                }
                //更新之后就要将左边界做右移操作(这个时候还是将第一个需要的字符移出。count需要++)
                need[s[left]] ++;
                left ++;
                count ++;
            }
            right ++; //right 先增加
        }
        return size != INT_MAX ? s.substr(start ,size) : "";
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值