zoukankan      html  css  js  c++  java
  • 76. Minimum Window Substring

    题目链接

    76. Minimum Window Substring

    题目描述

    给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
    注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

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

    提示:
    1 <= s.length, t.length <= 105
    s 和 t 由英文字母组成

    思路

    用滑动窗口解决,维护一个左指针和一个右指针。

    代码及解析

    class Solution {
    public:
        string minWindow(string s, string t) {
            map<char, int> needs;
            //needs表示当前在s串中需要遍历到的某个字符的数量,
            //当needs['a']>0的时候,表示还期待往右遍历到a字符
            //当needs['a']=0的时候,表示目前在s串中遇到的a字符的数量已经和t串中a字符的数量相等了
            //当needs['a']<0的时候,表示目前在s串中遇到的a字符的数量已经比t串中a字符的数量还要多了
            map<char, bool> flag;
            for (auto e : t) {
                needs[e]++;
                flag[e] = true;
            }
    
            int l = 0, r = 0, min_l = 0, min_size = INT_MAX, cnt = 0;
            //cnt表示当前s串中已经满足t串中字符的数目,
            //当cnt==t.size()的时候表示s串中已经满足t串的所有字符了
            for (; r < s.size(); r++) {
                //满足t串中的一个字符,计数器加一,
                //注意,只有needs[s[r]]减完1之后还大于或者等于0,才表示这次在s中遇到的s[r]字符是有效的
                //比如t串只有2个a字符,当在s中遇到第3个a字符的时候,我们只需要让--needs['a'],
                //此时needs['a'] = -1,表示当前在s中遇到的a字符数目已经多了一个 
                if (--needs[s[r]] >= 0) {
                    cnt++;
                }
    
                while (cnt == t.size()) {
                    //当前s串[l, r]之间的字符已经满足t了,但是可能不是最短的,
                    //意味着这段区间可能要么有些字符是t中不需要的,
                    //要么是对应的needs小于0,即相应的字符出现次数太多了
                    //那么为了达到最短的要求,就需要不断把左边界往右移动,即收缩边界
                    //移动之前首先判断当前[l,r]这个字串的长度是否是小于之前的最小长度min_size
                    //由于最开始min_size设置为了INT_MAX,所以当第一次走到这里的时候是一定满足条件的
                    if (r - l + 1 < min_size) {
                        min_l = l;//更新最小左边界
                        min_size = r - l + 1;//更新min_size
                    }
    
                    if (flag[s[l]] && ++needs[s[l]] > 0) {
                        //这段代码比较关键
                        //如果当前l位置的字符是t中出现过的,那么由于后面左边界会向右移动
                        //那么会出现两种情况:
                        //1.假设之前needs[s[l]]刚好等于0,那么当++needs[s[l]]之后就大于0,说明去掉当前字符已经不满足t串中s[l]字符的数量了,也就意味着我们满足t串字符数目要减一。
                        //2.设之前needs[s[l]]小于0,那么当++needs[s[l]]之后就还是小于或者等于0,这时候不需要更新cnt
                        //其实这段逻辑就是和上面的代码相对应的,只不过这里还有一种情况,就是当前l处的字符根本不是t中需要的,这种情况,只需要把l++即可。
                        /*
                        if(--needs[s[r]] >= 0){
                            cnt++;
                        }
                        */
                        cnt--;
                    }
    
                    //注意,我们这里是一定会收缩左边界的,问题来了,假设我们现在[l,r]之间的字符串刚好是我们目标字符串,那么l向右收缩之后,不是不符合条件了吗?那怎么记录这个位置的左边界和有边界呢?
                    //没错,这个就是通过min_l和min_size记录的,所以我们左边界和右边界都是在往右移动,只不过我们根据条件来更新min_l和min_size。
                    l++;//收缩左边界
                }
            }
    
            return min_size > s.size() ? "" : s.substr(min_l, min_size);
        }
    };
    
    只有0和1的世界是简单的
  • 相关阅读:
    使用makeself创建安装文件
    Java类的多态机制
    LintCode 带最小值操作的栈
    js限制checkbox选中个数
    Java Collection框架—List set map 的异同世界
    利用runtime动态生成对象?
    2014-3-4 大规模无缝水陆导航图
    atitit。全局变量的设计与实现 java php的异同
    PHP从入门到精通(四)
    PHP从入门到精通(三)
  • 原文地址:https://www.cnblogs.com/nullxjx/p/14973407.html
Copyright © 2011-2022 走看看