Minimum Window Substring


题目描述

Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string “”.
The testcases will be generated such that the answer is unique.
A substring is a contiguous sequence of characters within the string.

输入描述

输入满足以下条件:

  • m == s.length
  • n == t.length
  • 1 <= m, n <= 105
  • s and t consist of uppercase and lowercase English letters.

示例

输入

s = “ADOBECODEBANC”, t = “ABC”

输出

“BANC”

解释

The minimum window substring “BANC” includes ‘A’, ‘B’, and ‘C’ from string t.

分析

显然,可以通过枚举区间的起点和终点暴力解决这个问题,但时间复杂度过高,是否存在一种只需遍历一遍字符串就能得到结果的方法呢?

利用滑动窗口的思想,就可以扫描一遍字符串求解该问题。

本题的滑动窗口解法的伪码如下:

string s, t;
    // 在 s 中寻找 t 的「最小覆盖子串」
    int left = 0, right = 0;
    string res = s;
    
    while(right < s.size()) {
        window.add(s[right]);
        right++;
        // 如果符合要求,说明窗口构造完成,移动 left 缩小窗口
        while (window 符合要求) {
            // 如果这个窗口的子串更短,则更新 res
            res = minLen(res, window);
            window.remove(s[left]);
            left++;
        }
    }
    return res;

目前已经明确了可以通过一遍扫描字符串解决问题,那该如何高效的判断当前窗口是否满足要求就成为了问题的关键。我们可以维护一个字典来实现满足要求的判定。

AC代码


class Solution
{
public:
    string minWindow(string s, string t)
    {
        unordered_map<char, int> tm;
        for (auto i : t)
            tm[i]++;
        int l = 0, r = 0;
        int ansl, len = -1, cnt = 0;
        while (r < s.size())
        {
            if (tm.find(s[r]) != tm.end())
            {
                if (tm[s[r]] > 0)
                    cnt++;
                tm[s[r]]--;
            }
            while (cnt == t.size() && l <= r)
            {
                if (len == -1 || len > r - l + 1)
                {
                    len = r - l + 1;
                    ansl = l;
                }
                if (tm.find(s[l]) != tm.end())
                {
                    if (tm[s[l]] >= 0)
                        cnt--;
                    tm[s[l]]++;
                }
                l++;
            }
            r++;
        }
        return len == -1 ? "" : s.substr(ansl, len);
    }
};

文章作者: Kong Aobo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Kong Aobo !
  目录