zoukankan      html  css  js  c++  java
  • 76. 最小覆盖子串(Minimum Window Substring)

    题目描述:

    给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。

    示例:

    输入: S = "ADOBECODEBANC", T = "ABC"
    输出: "BANC"
    说明:

    如果 S 中不存这样的子串,则返回空字符串 ""。
    如果 S 中存在这样的子串,我们保证它是唯一的答案。

    解题思路:

      这道题用双指针滑动窗口完成。大体思路是记录一个区间,当区间符合要求时,就滑动左边界收缩区间;当区间不符合要求时,就滑动右边界放大区间。每当区间符合要求时,就比较此时区间的值是否是最小值,如果是就更新最小值。

      在这道题中,判断区间是否符合要求稍微复杂一些,需要使用两个unordered_map,一个保存需要满足的字符,一个保存当前区间中的字符。还需要一个整数变量记录符合要求的字符数,从而避免每次都要遍历两个map来判断是否符合条件。过程如下:

      只要右边界没有到s的最大长度,就一直循环。循环中每次把右边界的值加入到区间中,假设加入的字符用ch表示,那么如果ch不在need_map中时,表示该字符没用,就继续循环。如果ch在need_map中,就令window_map中该字符对应的值加1,如果该值等于need_map中字符对应的值,就表示这个字符已经满足了,记录字符个数的变量matched_num加1。接着判断matched_num是否等于need_map中字符的数量,如果等于就表示该区间符合要求,就要收缩左边界。如果左边界的字符ch不在need_map中,同样说明该字符没用,继续收缩左边界。直到左边界字符ch在need_map中时,将window_map中ch对应的值减一,如果该值小于need_map中字符对应的值,就将matched_num减一,此时会跳出收缩左边界循环。

      注意每次区间符合条件时,都要记录此时的区间长度和起始位置,最后返回区间长度最小的子串。

      代码如下:

    class Solution {
    public:
        string minWindow(string s, string t) {
            int l = 0, r = 0, match_num = 0;
            unordered_map<char, int> needs, windows;
            int len = s.size() + 1, begin_pos;
    
            for (auto && ch : t)
                ++needs[ch];
            while (r != s.size()) {
                if (needs.count(s[r]) == 0) {
                    ++r;
                    continue;
                }
                if (++windows[s[r]] == needs[s[r]])
                    ++match_num;
                while (match_num == needs.size()) {
                    if (len > r - l + 1) {
                        len = r - l + 1;
                        begin_pos = l;
                    }
                    if (needs.count(s[l]) == 0) {
                        ++l;
                        continue;
                    }
                    if (--windows[s[l]] < needs[s[l]])
                        --match_num;
                    ++l;
                }
                ++r;
            }
            if (len == s.size() + 1)
                return "";
            else
                return s.substr(begin_pos, len);
        }
    };
  • 相关阅读:
    bzoj2438
    bzoj3040
    [AHOI2009]维护序列
    [JSOI2008]最大数
    洛谷3378堆模板
    洛谷1439
    洛谷2756
    bzoj1016
    洛谷1875
    [模板] 强连通分量
  • 原文地址:https://www.cnblogs.com/yxsrt/p/13236952.html
Copyright © 2011-2022 走看看