题目:

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).

For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".

Note:
If there is no such window in S that covers all characters in T, return the empty string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

链接:  http://leetcode.com/problems/minimum-window-substring/

题解:

也是一道卡了很久的题。最近工作也忙,面试也忙,装修房子也忙,都没时间好好刷题。每天下班就跑建材市场,买材料干活。现在小腿肚子上的肌肉一走路就疼-_____-!! 早上电面了GS,答得乱七八糟...不找借口,该刷题还是得刷。

还是采用sliding window。先把t的字符放入一个hashmap中,然后对s进行遍历。  遍历过程中先确定window的右边界,找到满足条件的右边界以后,返回去找左边界,对多余元素以及不在t中的元素,我们都要做相应处理。 完毕之后将window左边界向右移动一个距离,进行下次查找。时间复杂度是O(n)因为每个元素只被访问两次。 代码依然写得很罗嗦,二刷的时候一定要简练。好像也可以用Deque或者double linkedlist来做,要研究一下。

睡觉去了!

Time Complexity - O(n), Space Complexity - O(n)

public class Solution {
public String minWindow(String s, String t) {
if(s == null || t == null || s.length() == 0 || t.length() == 0)
return "";
HashMap<Character, Integer> tMap = new HashMap<>(); for(int i = 0; i < t.length(); i++) { //put t into tMap
if(tMap.containsKey(t.charAt(i)))
tMap.put(t.charAt(i), tMap.get(t.charAt(i)) + 1);
else
tMap.put(t.charAt(i), 1);
} int lo = 0, min = s.length() + 1, count = 0, minLo = -1; boolean hasWindowChar = false; HashMap<Character, Integer> sMap = new HashMap<>(); for(int i = 0; i < s.length(); i++) {
if(!hasWindowChar && !tMap.containsKey(s.charAt(i))) {
lo++;
continue;
} hasWindowChar = true; //found start index
if(!tMap.containsKey(s.charAt(i))) //skip char not in t
continue;
if(sMap.containsKey(s.charAt(i))) //put current char into sMap
sMap.put(s.charAt(i), sMap.get(s.charAt(i)) + 1);
else
sMap.put(s.charAt(i), 1); if(sMap.get(s.charAt(i)) <= tMap.get(s.charAt(i))) //if current char <= char count in tMap, add count
count++; if(count == t.length()) { //if count == t.length(), found one solution
while(lo <= i) { //find left limit of current min sliding window
if(sMap.containsKey(s.charAt(lo))) {
if(sMap.get(s.charAt(lo)) > tMap.get(s.charAt(lo))) { //more char in sMap than which in tMap
sMap.put(s.charAt(lo), sMap.get(s.charAt(lo)) - 1); //reduce char num in sMap
lo++; //increase left limit
} else //if equal count in sMap and in tMap, it's local min
break;
} else //char not in t, skip
lo++;
} if(i - lo + 1 < min) { //if local min < global min
min = i - lo + 1; //update global min (length)
minLo = lo; //update starting index of global min
} sMap.put(s.charAt(lo), sMap.get(s.charAt(lo)) - 1); //move left bound of sliding window
lo++;
count--;
} } return minLo >= 0 ? s.substring(minLo, minLo + min) : "";
}
}

二刷:

二刷又遇到这一题的时候有一种似曾相识的感觉,就象一个老朋友,静静等待你的来访...  -____-。也有用Bitmap来做的,速度可能更快一些。

下面我们来分析一下思路。

读完题目以后发现题目给定String s和t,要求s中包含t所有字符的的最短字符串。比如  s = abcc, t = abc,那么最短就是前面的abc。或者 s = cccab, t = abc,那么最短就是cab。

  1. 这里我们主要考虑先使用一个HashMap<Character, Integer> tMap来统计t里的字符和出现频率,然后使用滑动窗口的方法来解决这个问题。
  2. 我们需要另外一个HashMap来负责统计在遍历string s的时候,当前的字符和频率 = curMap
  3. 以及几个integer变量
    1. lo 表示当前窗口的最左边界
    2. count表示当前窗口里,也在t中出现过的字符数,注意这里不包含多余的字符,比如 s = caaab, t = aabc,那么中间多余的a不应该被计算入count里,因为是duplicate,但最短值仍然是caaab。
    3. minLo ,明楼表示到现在为止最短字符串的左边界, 初始化为 -1
    4. min表示到现在为止最短字符串的长度, 初始化为 s.length() + 1
    5. 最后返回结果的时候就判断minLo是否 >= 0,假如是,说明存在结果,那么我们只要返回s.substring(minLo, minLo + min)就可以了, 否则不存在,返回""
  4. 接下来我们从0开始遍历整个s字符串,在遍历的过程中有以下几种情况:
    1. 假设当前位置i字符为c, 假如 tMap中不包含这个字符。
      1. 假如curMap.size() == 0,这时候窗口的左边界肯定在位置i 左边,所以我们进行 lo++。然后我们continue,跳过位置i。
      2. 假如curMap.size() > 0,这时候因为我们已经有了左边界,这个位置虽然元素不在tMap里,但也要占一个count的坑,我们不改变lo, 直接continue,跳过位置i。
    2. 否则这个字符c在tMap里,我们可以把这个字符加入到当前的curMap里。 假如在这个加入操作以后,curMap.get(c) <= tMap.get(c),这时候可以增加count++,我们认为这次找到了一个t中的字符,而且不是重复。
    3. 当count == tLen, 这时候的window里包含了t中所有的字符,但有可能还有多余字符,那么我们现在固定右边界,回去查找精确的左边界
      1. 我们从lo到i开始遍历这个window, 假设s.charAt(lo) = loChar
      2. 假如loChar不在当前map里,说明它和count无关,我们可以lo++
      3. 否则,loChar在当前map里,这时候我们要进行判断
        1. 假如curMap.get(loChar) > tMap.get(loChar), 说明有duplicate,我们减少curMap中的loChar树木,并且lo++
        2. 否则curMap的loChar数目和tMap中正好相等,这时候我们找到了合理的左边界,break跳出window的遍历
      4. 此时我们要对这个window的长度 i - lo + 1与之前保存的最小window长度min进行比较,假如这个window更短,我们更新min = i - lo + 1,并且更新minLo = lo
      5. 完后,我们要把window的左边界元素减少一个,并且count--,然后lo++,就是把窗口的左边界向右移动一个单位,来继续寻找接下来可能符合条件的窗口
  5. 最后根据minLo的位置我们返回结果。

Java:

Time Complexity - O(n), Space Complexity - O(n)

public class Solution {
public String minWindow(String s, String t) {
if (s == null || t == null || s.length() < t.length()) {
return "";
}
int sLen = s.length(), tLen = t.length();
Map<Character, Integer> tMap = new HashMap<>();
for(int i = 0; i < tLen; i++) { //put t into tMap
if(tMap.containsKey(t.charAt(i)))
tMap.put(t.charAt(i), tMap.get(t.charAt(i)) + 1);
else
tMap.put(t.charAt(i), 1);
}
Map<Character, Integer> curMap = new HashMap<>();
int lo = 0, minLo = -1, min = s.length() + 1, count = 0; for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (!tMap.containsKey(c)) {
if (curMap.size() == 0) {
lo++;
}
continue;
}
if (curMap.containsKey(c)) {
curMap.put(c, curMap.get(c) + 1);
} else {
curMap.put(c, 1);
}
if (curMap.get(c) <= tMap.get(c)) {
count++;
}
if (count == tLen) {
for (int j = lo; j < i; j++) {
char loChar = s.charAt(j);
if (!curMap.containsKey(loChar)) {
lo++;
} else if (curMap.get(loChar) > tMap.get(loChar)) {
curMap.put(loChar, curMap.get(loChar) - 1);
lo++;
} else {
break;
}
}
if (i - lo + 1 < min) {
min = i - lo + 1;
minLo = lo;
}
curMap.put(s.charAt(lo), curMap.get(s.charAt(lo)) - 1);
lo++;
count--;
}
}
return minLo >= 0 ? s.substring(minLo, minLo + min) : "";
}
}

2/5/2016:

中午组织同事们在麒麟金阁吃了早茶,一共来了十一位,大家都很高兴。我也提前给大家拜个早年,希望大家身体健康,事业进步,幸福美满。

三刷:

写起来确实费劲 -____-!! 速度很慢,并不是很好的方法,要改进。

Java:

public class Solution {
public String minWindow(String s, String t) {
if (s == null || t == null || s.length() < t.length()) return "";
Map<Character, Integer> tMap = new HashMap<>();
int sLen = s.length(), tLen = t.length();
for (int i = 0; i < tLen; i++) {
char c = t.charAt(i);
if (!tMap.containsKey(c)) tMap.put(c, 1);
else tMap.put(c, tMap.get(c) + 1);
}
Map<Character, Integer> sMap = new HashMap<>();
int count = 0, lo = 0, minLo = -1, len = s.length() + 1; for (int i = 0; i < sLen; i++) {
char sc = s.charAt(i);
if (!tMap.containsKey(sc)) continue; if (!sMap.containsKey(sc)) sMap.put(sc, 1);
else sMap.put(sc, sMap.get(sc) + 1); if (sMap.get(sc) <= tMap.get(sc)) count++; if (count == tLen) {
while (!tMap.containsKey(s.charAt(lo)) || sMap.get(s.charAt(lo)) > tMap.get(s.charAt(lo))) {
if (tMap.containsKey(s.charAt(lo)) && sMap.get(s.charAt(lo)) > tMap.get(s.charAt(lo))) {
sMap.put(s.charAt(lo), sMap.get(s.charAt(lo)) - 1);
}
lo++;
}
if (i - lo + 1 < len) {
minLo = lo;
len = i - lo + 1;
}
sMap.put(s.charAt(lo), sMap.get(s.charAt(lo)) - 1);
lo++;
count--;
}
}
return minLo >= 0 ? s.substring(minLo, minLo + len) : "";
}
}

Reference:

https://leetcode.com/discuss/72701/here-10-line-template-that-can-solve-most-substring-problems

https://leetcode.com/discuss/10337/accepted-o-n-solution

https://leetcode.com/discuss/5469/is-the-length-of-t-considered-constant-or-m

https://leetcode.com/discuss/32851/share-my-neat-java-solution

https://leetcode.com/discuss/79792/the-fast-7ms-o-n-java-solution-use-only-one-array-without-map

76. Minimum Window Substring的更多相关文章

  1. 刷题76. Minimum Window Substring

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

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

  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 解题思路

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

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

  6. 76. Minimum Window Substring(hard 双指针)

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

  7. 76. Minimum Window Substring (JAVA)

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

  8. [LC] 76. Minimum Window Substring

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

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

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

随机推荐

  1. 笔记 php.ini配置文件中magic_quotes_gpc, magic_quotes_runtime的作用是什么?应该开启还是关闭?

    默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET.POST 和 COOKIE 数据自动运行 addslashes().不要对已经被 magic_quotes_gp ...

  2. C#获取数据库中的Instance

    如果我现在要写个代码生成器,连接数据库,那你得知道有哪些Database存在吧,不然咋整? 在VS中我们添加一个ADO.NET的实体模型 在选择数据库名称的时候就是获取了数据库中Database In ...

  3. Swift学习:闭包(Closures)

    /* 闭包(Closures)* 闭包是自包含的功能代码块,可以在代码中使用或者用来作为参数传值.* 在Swift中的闭包与C.OC中的blocks和其它编程语言(如Python)中的lambdas类 ...

  4. Jira 6.0.3 安装与破解

    如果你还没有使用Jira做项目跟踪与管理,那就赶紧试用一下吧.下面教你一步一步安装Jira 6.0.3,以及如何破解试用版. 一. 安装准备   1. 去Jira官方网站下载http://www.at ...

  5. DB天气app冲刺二阶段第十一天(完结)

    今天最后一天冲刺了,明天就不再冲刺了..已经把所有的技术的问题还有设计的问题都弄好了吧应该说 至少目前来说是的.因为有的实现不了的或者需要耗费时间的已经果断舍弃了,然后需要完善的也都基本完善了. 现在 ...

  6. 论坛类应用双Tableview翻页效果实现

    作为一名篮球爱好者,经常使用虎扑体育,虎扑体育应用最核心的部分就是其论坛功能,无论哪个版块,论坛都是其核心,而其论坛部分的实现又别具一格,它以两个tableview的形式翻页滚动显示,而不是常见的那种 ...

  7. C# 浅谈委托----温故而知新

    先看看委托的概述: •委托类似于 C++ 函数指针,但它们是类型安全的. • 委托允许将方法作为参数进行传递. • 委托可用于定义回调方法. • 委托可以链接在一起:例如,可以对一个事件调用多个方法. ...

  8. WPF 多线程处理(6)

    WPF 多线程处理(1) WPF 多线程处理(2) WPF 多线程处理(3) WPF 多线程处理(4) WPF 多线程处理(5) WPF 多线程处理(6) 以下是子窗体的UI: <Window ...

  9. dbutils 执行sql返回的数据类型

    //ArrayHandler: 把结果集中的第一行数据转成对象数组 //ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中 //BeanHandler:将结 ...

  10. 视频学习_css基础学习

    块状元素 block element 容器元素  设置高宽 width height  可以容纳 文本 内脸 和其他块状 霸道  独占一行 特例:form  只容纳 块状元素 常见元素 http:// ...