作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址: https://leetcode.com/problems/minimum-window-substring/description/

题目描述

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

Example:

Input: S = "ADOBECODEBANC", T = "ABC"
Output: "BANC"

Note:

  • If there is no such window in S that covers all characters in T, return the empty string “”.
  • If there is such window, you are guaranteed that there will always be only one unique minimum window in S.

题目大意

在S中找出包含T的全部字符的最小子串。

解题方法

滑动窗口

统计字符出现的个数,而且时间复杂度要求 O(N),明显使用滑动窗口解题。和567. Permutation in String有点相似,都是要求子字符串满足一定的次数要求。

什么场景下使用滑动窗口? 答:如果我们找到了一个满足要求的区间,并且当区间的右边界再向右扩张已没有意义,此时可以移动左边界到达不满足要求的位置。再移动右边界,持续如此,直到区间的右边界到达整体的结束点。

比如本题:当我们在 s 中找到了一个覆盖了 t 的所有字符的子字符串 s[left, right] 时,如果再向右移动 right ,扩大范围后的新的子字符串仍然覆盖了 t 的所有字符,但新子字符串一定不是最短了(题目要求最短的子字符串)。这就是我说的右边界向右扩张已没有意义,此时应该移动左边界直至使得区间不满足子字符串不满足覆盖 t 。

本题做法:

  1. 定义 left, right 分别指向滑动窗口的左右边界,子字符串为 s[left, right] 双闭区间。

  2. 使用 right 指针向右搜索,同时要记录在 s[left, right] 这个区间覆盖了多少个 t 中的元素。如果在 s[left,right] 内,覆盖了所有 t 的元素,说明这个区间是符合要求的一个区间。此时 right指针再向右移动已经没有意义。

  3. 现在要移动 left 指针,直至 s[left,right] 子字符串不能覆盖 t

统计字符出现的次数可以直接使用字典,但如果对于每个 s[left, right] 区间都去统计一遍所有元素出现的次数,会导致方法复杂度会增加到 O(N ^ 2),因此不能通过 OJ。必须快速地判定 s[left,right] 是否覆盖了 t

题目说,在 s[left, right] 闭区间内的元素出现个数应该把 t 中所有的元素都包含,所以我们定义 scount 字典变量保存s[left, right] 闭区间中各个元素出现的次数;定义 tcount 字典变量保存 t 中的元素出现次数。 cnt 变量储存 s[left, right] 闭区间中已经覆盖了 t 中的多少个元素,如果 cnt == t.size() 说明该子数组覆盖了 t

在移动 left 指针的时候要注意存储最短的子串,使用的 minLen 变量存储当前满足题目要求的最短子串长度。当某个子字符串区间满足要求时,根据minLen更新最终的最短子串结果 res

这个题难点就在于维护 cnt,它的作用仅仅为了提高速度。

时间复杂度是O(N),空间复杂度是O(N)

这个题的 C++ 代码如下:

class Solution {
public:
string minWindow(string s, string t) {
int M = s.size();
int N = t.size();
unordered_map<char, int> scount;
unordered_map<char, int> tcount;
// left and right means [left, right] of s
// count means the same chars of s[left, right] with t
int left = 0, right = 0, count = 0;
int minLen = INT_MAX;
string res;
for (char c : t)
++tcount[c];
while (right < M) {
char c = s[right];
scount[c] += 1;
if (tcount.count(c) && scount[c] <= tcount[c]) {
count += 1;
}
while (left <= right && count == N) {
if (minLen > right - left + 1) {
minLen = right - left + 1;
res = s.substr(left, minLen);
}
char l = s[left];
scount[l] -= 1;
if (tcount.count(l) && scount[l] < tcount[l])
count -= 1;
++left;
}
++right;
}
return res;
}
};

参考资料:

https://leetcode.com/articles/minimum-window-substring/
http://www.cnblogs.com/grandyang/p/4340948.html

日期

2018 年 10 月 3 日 —— 玩游戏导致没睡好,脑子是浆糊。
2020 年 5 月 23 日 —— 这次编辑时对滑动窗口有了更深的理解

【LeetCode】76. Minimum Window Substring 最小覆盖子串(Python & C++)的更多相关文章

  1. [LeetCode] 76. Minimum Window Substring 最小窗口子串

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  2. [LeetCode] 76. Minimum Window Substring 解题思路

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  3. [leetcode]76. Minimum Window Substring最小字符串窗口

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  4. Leetcode#76 Minimum Window Substring

    原题地址 用两个指针分别记录窗口的左右边界,移动指针时忽略那些出现在S种但是没有出现在T中的字符 1. 扩展窗口.向右移动右指针,当窗口内的字符即将多于T内的字符时,停止右移 2. 收缩窗口.向右调整 ...

  5. 刷题76. Minimum Window Substring

    一.题目说明 题目76. Minimum Window Substring,求字符串S中最小连续字符串,包括字符串T中的所有字符,复杂度要求是O(n).难度是Hard! 二.我的解答 先说我的思路: ...

  6. 【LeetCode】76. Minimum Window Substring

    Minimum Window Substring Given a string S and a string T, find the minimum window in S which will co ...

  7. 【一天一道LeetCode】#76. Minimum Window Substring

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  8. [Leetcode][JAVA] Minimum Window Substring

    Given a string S and a string T, find the minimum window in S which will contain all the characters ...

  9. lintcode 中等题:minimum window substring 最小子串覆盖

    题目 最小子串覆盖 给定一个字符串source和一个目标字符串target,在字符串source中找到包括所有目标字符串字母的子串. 样例 给出source = "ADOBECODEBANC ...

随机推荐

  1. mysql-centos8下安装

    参考文章 1.下载安装包 客服端与服务端 依赖包 2.linux下检查是否安装 rpm -qa | grep -i mysql 安装过会显示软件名称,没安装过就是空的 3.安装包传到虚拟机 先需要把安 ...

  2. The Go tools for Windows + Assembler很好玩

    我想用python做个tiny BASIC编译器.赋值和加减乘除,IF和FOR. 语法分析python有ply包,用ply.lex和ply.yacc做个计算器很简单,我已经做了. 做个解释器应该也不难 ...

  3. C语言time函数获取当前时间

    以前放了个链接,但是原作者把博文删了,这里放一个获取时间的代码,已经比较详细所以不做注释 #include<stdio.h> #include<time.h> #include ...

  4. 【Java 泛型】之 <? super T> 和<? extends T> 中 super ,extends如何理解?有何异同?

    Java 泛型 <? super T> 和<? extendsT>中 super ,extends怎么 理解?有何不同? 简介 前两篇文章介绍了泛型的基本用法.类型擦除以及泛型 ...

  5. 解决ViewPager与ScrollView 冲突

    ViewPager来实现左右滑动切换tab,如果tab的某一项中嵌入了水平可滑动的View就会让你有些不爽,比如想滑动tab项中的可水平滑动的控件,却导致tab切换. 因为Android事件机制是从父 ...

  6. GO瞬间并发数控制

    var wg2 sync.WaitGroup wg2.Add(nums) xc :=0 parallelNum := plt.MaxParallel var waitCount int32 = 0 f ...

  7. java Map集合类

    ---恢复内容开始--- Map提供了一个更通用的元素存储方法,Map集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值. 了解Map接口和方法 ...

  8. Linux系统信息查看命令(ZZ)

    http://hi.baidu.com/thinkdifferent/blog/item/22f4a80161630e011d958384.html转自一个baidu师兄的博客,很好的一个总结,推荐下 ...

  9. 应用springMVC时如果配置URL映射时如下配置

    应用springMVC时如果配置URL映射时如下配置 [html] view plaincopy<servlet> <servlet-name>appServlet</s ...

  10. 过滤敏感词工具类SensitiveFilter

    网上过滤敏感词工具类有的存在挺多bug,这是我自己改用的过滤敏感词工具类,目前来说没啥bug,如果有bug欢迎在评论指出 使用前缀树 Trie 实现的过滤敏感词,树节点用静态内部类表示了,都写在一个 ...