76. Minimum Window Substring
题目:
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。
- 这里我们主要考虑先使用一个HashMap<Character, Integer> tMap来统计t里的字符和出现频率,然后使用滑动窗口的方法来解决这个问题。
- 我们需要另外一个HashMap来负责统计在遍历string s的时候,当前的字符和频率 = curMap
- 以及几个integer变量
- lo 表示当前窗口的最左边界
- count表示当前窗口里,也在t中出现过的字符数,注意这里不包含多余的字符,比如 s = caaab, t = aabc,那么中间多余的a不应该被计算入count里,因为是duplicate,但最短值仍然是caaab。
- minLo ,明楼表示到现在为止最短字符串的左边界, 初始化为 -1
- min表示到现在为止最短字符串的长度, 初始化为 s.length() + 1
- 最后返回结果的时候就判断minLo是否 >= 0,假如是,说明存在结果,那么我们只要返回s.substring(minLo, minLo + min)就可以了, 否则不存在,返回""
- 接下来我们从0开始遍历整个s字符串,在遍历的过程中有以下几种情况:
- 假设当前位置i字符为c, 假如 tMap中不包含这个字符。
- 假如curMap.size() == 0,这时候窗口的左边界肯定在位置i 左边,所以我们进行 lo++。然后我们continue,跳过位置i。
- 假如curMap.size() > 0,这时候因为我们已经有了左边界,这个位置虽然元素不在tMap里,但也要占一个count的坑,我们不改变lo, 直接continue,跳过位置i。
- 否则这个字符c在tMap里,我们可以把这个字符加入到当前的curMap里。 假如在这个加入操作以后,curMap.get(c) <= tMap.get(c),这时候可以增加count++,我们认为这次找到了一个t中的字符,而且不是重复。
- 当count == tLen, 这时候的window里包含了t中所有的字符,但有可能还有多余字符,那么我们现在固定右边界,回去查找精确的左边界
- 我们从lo到i开始遍历这个window, 假设s.charAt(lo) = loChar
- 假如loChar不在当前map里,说明它和count无关,我们可以lo++
- 否则,loChar在当前map里,这时候我们要进行判断
- 假如curMap.get(loChar) > tMap.get(loChar), 说明有duplicate,我们减少curMap中的loChar树木,并且lo++
- 否则curMap的loChar数目和tMap中正好相等,这时候我们找到了合理的左边界,break跳出window的遍历
- 此时我们要对这个window的长度 i - lo + 1与之前保存的最小window长度min进行比较,假如这个window更短,我们更新min = i - lo + 1,并且更新minLo = lo
- 完后,我们要把window的左边界元素减少一个,并且count--,然后lo++,就是把窗口的左边界向右移动一个单位,来继续寻找接下来可能符合条件的窗口
- 假设当前位置i字符为c, 假如 tMap中不包含这个字符。
- 最后根据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的更多相关文章
- 刷题76. Minimum Window Substring
一.题目说明 题目76. Minimum Window Substring,求字符串S中最小连续字符串,包括字符串T中的所有字符,复杂度要求是O(n).难度是Hard! 二.我的解答 先说我的思路: ...
- 【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 ...
- [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 ...
- [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 ...
- [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 ...
- 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 ...
- 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 ...
- [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 ...
- 【一天一道LeetCode】#76. Minimum Window Substring
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...
随机推荐
- CSS练习
看到一个CSS参考手册:http://css.doyoe.com/ 感谢感谢!
- 移植Oracle procedure 到 postgresql
1.登录postgresql psql -h 192.168.137.131 -p 5432 postgres satusc@6789#JKL 2.创建用户 CREATE USER name thun ...
- Boost的自动链接功能
Boost是一个强大的C++第三方库,但是Boost的各种问题实在是很让人蛋疼.我搜到过一篇文章关于LuaBind使用Boost Build管理工具来管理源代码以及编译的博文,其第一句话就是Fuck ...
- Configure Log Shipping
准备工作 两台装有的Windows Server 2012R2以及SQL Server 2012的服务器 下载评估版 Windows Server 2012 R2 下载 Microsoft SQL S ...
- Storm集群安装详解
storm有两种操作模式: 本地模式和远程模式. 本地模式:你可以在你的本地机器上开发测试你的topology, 一切都在你的本地机器上模拟出来; 远端模式:你提交的topology会在一个集群的机器 ...
- Android存储机制之Preference
Preference提供了一种轻量级的数据存取方法,主要是数据比较少的配置信息.它以键值对的方式将数据保存在一个XML配置文件中. 使用Preference方式来存取数据,用到了SharedPrefe ...
- VBS基础篇 - 条件语句
经常地,当我们编写代码时,我们需要根据不同的判断执行不同操作,我们可以使用条件语句完成这个工作. If...Then...Else 在下面的情况中,您可以使用 If...Then...Else 语句: ...
- C# type - IsPrimitive
Type t = typeof(string); if (t.IsPrimitive)//not { Console.WriteLine("string is a Primitive&quo ...
- java mail实现Email的发送,完整代码
java mail实现Email的发送,完整代码 1.对应用程序配置邮件会话 首先, 导入jar <dependencies> <dependency> <groupId ...
- 【BZOJ】【1833】【ZJOI2010】count 数字计数
数位DP Orz iwtwiioi 学习了一下用记忆化搜索来捉题的新姿势……但没学会TAT,再挖个坑(妈蛋难道对我来说数位DP就是个神坑吗……sigh) //BZOJ 1833 #include< ...