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. ora-12899解决方法

    在使用ORACLE的过程中,会出现各种各样的问题,各种各样的错误,其中ORA-12899就是前段时间我在将数据导入到我本地机器上的时候一直出现的问题.不过还好已经解决了这个问题,现在分享一下,解决方案 ...

  2. Codeforces Beta Round #77 (Div. 2 Only)

    Codeforces Beta Round #77 (Div. 2 Only) http://codeforces.com/contest/96 A #include<bits/stdc++.h ...

  3. 微信小程序开发——打开另一个小程序

    微信小程序打开另一个小程序,有两种方法:1.超链接:2.点击按钮. 全局配置: 跳转到其他小程序,需要在当前小程序全局配置中配置需要跳转的小程序列表,代码如下: App.json { ... &quo ...

  4. gitbook的学习

    gitbook安装与使用之windows下搭建gitbook平台 最近需要在GitBook中去阅读电子书 安装nodejs cnpm安装gitbook 解压书籍文件,并cd到书籍文件目录 gitboo ...

  5. django具体操作(七)

    新增组件 使用 python manage.py startapp新建一个app,并且在settings中注册,添加stark.apps.StarkConfig, 然后在stark的apps中添加re ...

  6. java项目中常见的异常及处理

    Java开发中常见异常及处理方法 1.JAVA异常 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API ...

  7. udevadm命令详解

    udevadm 后接一个命令和命令指定选项.它控制了udev运行的行为,处理内核事件,控制事件队列,并且提供简单的调试机制. 选项: --debug 打印错误信息 --version 打印版本信息 - ...

  8. MD5加密和sha加密

    sha加密原理Algorithm)又叫安全哈希加密技术,是当今世界最先近的加密算法.主要用于文件身份识别.数字签名和口令加密等. 对于明文信息A,通过SHA1算法,生成一条160位长的识别码B.且明文 ...

  9. MongoDB的索引(六)

    数据准备:在mongodb命令行终端执行如下代码 for(var i=0;i<100000;i++) { ... db.users.insert({username:"user&quo ...

  10. Jfinal适用于条件查询的动态SQL语句生成工具

    条件查询是可能有为空字段,拼接SQL语句时候要屏蔽掉这些字段. package cn.pangpython.utils; import java.util.Iterator; import java. ...