0%

LeetCode 076 Minimum Window Substring

Description

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:

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

Difficulty: Hard

Code:

1
2
3
4
5
class Solution {
public String minWindow(String s, String t) {

}
}

题意

给定一个字符串S和字符串T,从S中找出最短的子字符串能包含T中所有的字符,复杂度要求O(n)。

Solution 1

使用双指针来定义滑动窗口,窗口右侧从s左侧往右移动,直到包含所以t的字符,然后将窗口左侧右移,去除掉不需要的部分。

定义计数器cnt表示当前窗口包含t中字符的个数,minLen是最小窗口的长度,res是窗口对应的子字符串。

  1. 先扫一遍t将对应的字符及其出现次数放入HashMap中
  2. 开始遍历s,遍历到的字符对应HashMap中的value减1,若减1后仍大于等于0,
    说明当前遍历到的字母是T串中的字母并且没有超过出现的次数,cnt加1
  3. 若cnt等于t的长度,开始一个循环,循环中更新minLen和res。
    然后将子窗口的左边界向右移,将该字符对应HashMap中的value加1,若加1后大于0,
    说明少了一个t中的字母,那么cnt自减1,表示没有匹配成功,然后移动左边界
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public String minWindow(String s, String t) {
String res = "";
HashMap<Character,Integer> map = new HashMap<Character,Integer>();
for(char c:t.toCharArray()){
if(map.containsKey(c)){
map.put(c,map.get(c)+1);
}else{
map.put(c,1);
}
}
int left=0, count=0, minLen=Integer.MAX_VALUE;
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(!map.containsKey(c)){
map.put(c,0);
}
map.put(c,map.get(c)-1);
if(map.get(c)>=0) count++;
while(count==t.length()){
if(minLen>i-left+1){
minLen=i-left+1;
res=s.substring(left,i+1);
}
char l=s.charAt(left);
map.put(l,map.get(l)+1);
left++;
if(map.get(l)>0) count--;
}
}
return res;
}
}

时间复杂度: O(n)。

空间复杂度: O(1)。

Solution 2

由于只有256个字符,可以用int数组来代替HashMap,提高运行速度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public String minWindow(String s, String t) {
int left = 0, cnt = 0, minLeft=-1, minLen = Integer.MAX_VALUE;
int[] map = new int[256];
for(char c:t.toCharArray()){
map[c]++;
}
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(--map[c]>=0){
cnt++;
}
while(cnt==t.length()){
if(minLen>i-left+1){
minLen=i-left+1;
minLeft=left;
}
if(++map[s.charAt(left)]>0) cnt--;
left++;
}
}
return minLeft==-1 ? "" : s.substring(minLeft,minLeft+minLen);
}
}

时间复杂度: O(n)。

空间复杂度: O(1)。