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 ...
随机推荐
- 提高Linux安全性--hosts.allow, hosts.deny 文件修改方法
有一种办法来提高Linux安全性--修改 hosts.allow , hosts.deny 这2个文件来配置 允许某个ip访问, 或者禁止访问. 可以通过这种方式设置限制 sshd 的远程访问, 只允 ...
- 《零成本实现Web自动化测试--基于Selenium》 第四章 Selenium 命令
Selenium 命令,通常被称为Selenese,由一系列运行测试案例所需要的命令构成.按顺序排列这些命令就构成了测试脚本. 一. 验证颜面元素 1.Assertion或者Verification ...
- WPF 控件DataGrid绑定
WPF 手动绑定 DataGrid 例子:前台:<DataGrid AutoGenerateColumns="False" Name="dataGrid1" ...
- HTTP 错误 404.3 - Not Found
在使用win2012服务器上的IIS发布网页的时候,出现下面的错误 解决办法: 将应用程序开发下的所有功能都安装. 如果上面的方法没解决问题的话,那么看看下图中的这些安装没,没有的话就继续安装.
- adbd cannot run as root in production builds
首先必须保证手机已经root过,可以通过以下验证: $ adb shell root@dior:/ $ su root@dior:/ # 1 2 3 执行命令后,$ 变为 # 即 root 成功 但是 ...
- java排序集锦
java实现排序的一些方法,来自:http://www.javaeye.com/topic/548520 package sort; import java.util.Random; /** * 排序 ...
- 自定义控件(模仿微信ToggleButton控件)
弄过android开发的都知道,系统有一个默认的ToggleButton,但很多人都觉得他很难看,当然也包括我.如果你感觉他不难看,那你就继续使用系统的吧,这篇文章对你来说是多余的了. 今天来写一个模 ...
- github pages
http://zyip.github.io/facemaker/index echo "hello world" >>hello.htm git init git ad ...
- anroid ndk编译ffmpeg 引用librtmp libx264
Ffmpeg 无处不在,自然android系统少不了它,折腾了不少时间完成 ndk编译ffmpeg,生成so库中引用了外部库librtmp,libx264.条条大路通罗马, 也许还有别的更好的方法去完 ...
- Matlab与科学计算的基本运算
各种允许的比较关系 >, >=, <, <=, ==,~=, find(), all(), any() 例:>> A=[1,2,3;4,5,6;7,8,0]A = ...