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.

Idea 1. Sliding window with two pointers. The right pointer to expand the window while fixing the left window and the left pointer to shrink the given window while fixing the right window. At any time only one of these pointer move and the other remains fixed. 经典的滑动窗口的方法, 用左右2各点滑动形成的窗口中找寻符合条件的窗口。这题麻烦的地方是如何快速的判断符合条件的窗口(letterSeen == T.length),包含T的所有字母的最小窗口, 包含T的所有字母的窗口字母个数和T至少一样长。T中可能有重复字母,需要用map来记下每个字母出现的个数。

如何update letterSeen?

  ++letterSeen if window[right] <= letterT[right] after ++window[right]

  --letterSeen if window[left] < letterT[left] after --window[left]

Time complexity: O(S + T), in the worst case each element is visited twice, once by right pointer, once by the left pointer. (exactly loop time 2 * S + T)

Space complexity: O(T + S), depends on the dictionary size

1.a.建立2个map, 第一个letterT用来记下T中字母出现个数,第二个window记录滑动窗口中字母出现的个数, 判断窗口中出现的字母是不是符合条件的,比如s = "aab", t = "ab", letterT['a' - 'A'] = 1,  当right = 0, window['a'-'A'] = 1 <= 2, T中的字母扫了一个,letterSeen = 1; 当right = 1, window['a'-'A'] = 2 > letterT['a' - 'A'], 扫到的比T中还多,算是多余的,就不能加letterSeen, letterSeen = 1; 当right = 2,window['b'-'A'] = 1 <= letter['b'-'A'], letterSeen = 2 == T.length, "aab"是第一个符合条件的窗口;再固定右边活动左边来找是不是还有更小的,window['a'-'A'] = 1, letterSeen == T.length, "ab"符合条件; 继续右滑,window['a'-'A'] = 0 < T['a' - 'A'], letterSeen = 1 不符合条件。

++letterSeen if window[c-'A'] <= T[c-'A']

Note.

  window[c-'A']用作字母为key的map很方便

滑动左边不要忘记 ++left

 class Solution {
public String minWindow(String s, String t) {
int[] letterT = new int[256];
for(int i = 0; i < t.length(); ++i) {
++letterT[t.charAt(i) - 'A'];
} int[] window = new int[256];
int start = -1;
int letterSeen = 0;
int minLen = Integer.MAX_VALUE;
for(int left = 0, right = 0; right < s.length(); ++right) {
int keyRight = s.charAt(right) - 'A';
++window[keyRight];
if(window[keyRight] <= letterT[keyRight]) {
++letterSeen;
while(letterSeen == t.length()) {
if(right - left + 1 < minLen) {
minLen = right - left + 1;
start = left;
}
int keyLeft = s.charAt(left) - 'A';
--window[keyLeft];
if(window[keyLeft] < letterT[keyLeft]) {
--letterSeen;
}
++left;
}
}
} if(start == -1) {
return "";
}
return s.substring(start, start + minLen);
}
}

python

 class Solution:
def minWindow(self, s: str, t: str) -> str:
letterT = collections.Counter(t) window = collections.defaultdict(int)
left = 0
letterSeen = 0
start = -1
minLen = len(s) + 1
for right in range(len(s)): window[s[right]] += 1
if window[s[right]] <= letterT[s[right]]:
letterSeen += 1
while letterSeen == len(t):
if right - left + 1 < minLen:
start = left;
minLen = right - left + 1 window[s[left]] -= 1
if window[s[left]] < letterT[s[left]]:
letterSeen -= 1 left += 1 if start == -1:
return "" return s[start: start + minLen]

2.b 只需要一个map letterT, 用右滑动来减字母个数,左滑动来加字母个数,如果左边也扫到尾部,正好左右抵消还原原来的map.

 class Solution {
public String minWindow(String s, String t) {
int[] letterT = new int[256]; for(int i = 0; i < t.length(); ++i) {
++letterT[t.charAt(i) - 'A'];
} int lettersSeen = 0;
int minLen = Integer.MAX_VALUE;
int start = -1;
for(int left = 0, right = 0; right < s.length(); ++right) {
--letterT[s.charAt(right) - 'A'];
if(letterT[s.charAt(right) - 'A'] >= 0) {
++lettersSeen; while(lettersSeen == t.length()) {
if(right - left + 1 < minLen) {
minLen = right - left + 1;
start = left;
}
++letterT[s.charAt(left) - 'A'];
if(letterT[s.charAt(left) - 'A'] > 0) {
--lettersSeen;
}
++left;
}
}
} if(start == -1) {
return "";
}
return s.substring(start, start + minLen);
}
}

python:

 class Solution:
def minWindow(self, s: str, t: str) -> str:
letterT = collections.Counter(t) lettersSeen = 0
start = -1
minLen = len(s) + 1
left = 0
for right in range(len(s)):
if s[right] in letterT:
letterT[s[right]] -= 1
if letterT[s[right]] >= 0:
lettersSeen += 1 while lettersSeen == len(t):
if right - left + 1 < minLen:
minLen = right - left + 1
start = left if s[left] in letterT:
letterT[s[left]] += 1 if letterT[s[left]] > 0:
lettersSeen -= 1 left += 1 if start == -1:
return "" return s[start: start+minLen]

Minimum Window Substring LT76的更多相关文章

  1. 53. Minimum Window Substring

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

  2. Minimum Window Substring @LeetCode

    不好做的一道题,发现String Algorithm可以出很多很难的题,特别是多指针,DP,数学推导的题.参考了许多资料: http://leetcode.com/2010/11/finding-mi ...

  3. LeetCode解题报告—— Minimum Window Substring && Largest Rectangle in Histogram

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

  4. leetcode76. Minimum Window Substring

    leetcode76. Minimum Window Substring 题意: 给定字符串S和字符串T,找到S中的最小窗口,其中将包含复杂度O(n)中T中的所有字符. 例如, S ="AD ...

  5. 【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 ...

  6. 刷题76. Minimum Window Substring

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

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

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

  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. Java for LeetCode 076 Minimum Window Substring

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

随机推荐

  1. azkaban编译以及安装(调度系统)

    编译源码 下载azkaban源码 git clone https://github.com/azkaban/azkaban.git   jdk要求是1.8以上版本 export JAVA_HOME=/ ...

  2. React中innerHTML的坑

    [React中innerHTML的坑] 通过React Ref机制返回的对象,是一个阉割的DOM对象,并非原始DOM对象.比如,这个阉割版的DOM对象没有innerHTML对象. <button ...

  3. metasploit framework(二):记一次入侵

    msfconsole use 其中一个 exploit前台执行注入 后台执行shell 加-j 通过sessions查看后台执行的shell,可以看到这个会话的id号为2 进入会话,sessions ...

  4. Java 读取Excel 文件内容

    在一个项目中,有一个需求,是把excel文件的内容转换为xml格式展示.在学习如何操作的过程中,首先是如何获取excel文件,其中操作的代码如下: 1.首先是导入需要的 jar, 下载地址:https ...

  5. python计算两个数的百分比

    a和b是整数,计算a/b的百分比 a=3 b=7 a=float(a) b=float(b) 保留百分比后2位小数 print  "%.2f%%" % (a/b*100) '42. ...

  6. StringBuffer类和String类(原文地址 : http://www.cnblogs.com/springcsc/archive/2009/12/03/1616330.html)

    StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存 ...

  7. idea使用maven打包jar包

    1.在pom.xml中加入以下内容: <?xml version="1.0" encoding="UTF-8"?> <project xmln ...

  8. Mysql 索引与Key

    如果只是key的话,就是普通索引. mysql的key和index多少有点令人迷惑,单独的key和其它关键词结合的key(primary key)实际表示的意义是不同,这实际上考察对数据库体系结构的了 ...

  9. express 学习札记

    Enjoy yourself! 祝你玩得开心! I have no idea. 我没有头绪. I just made it! 我做到了!  I’ll see to it 我会留意的. Express ...

  10. 【mysql】分区表

    分区表是什么? 分区表可以按照事先创建的规则,对mysql的记录进行分组,每一个组具有一个独立的逻辑单元来存储该组的数据.典型的如:按照创建时间的年份分组,按照id的顺序分组(每1000万条数据分一个 ...