习题
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”
说明:
如果 S 中不存这样的子串,则返回空字符串 “”。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
算法
class Solution {
public String minWindow(String s, String t) {
int[] letterHash = new int[123];
String ret = "";
int cnt = 0 , min_len = Integer.MAX_VALUE , left = 0;
for(int i =0; i < t.length();i++)
letterHash[t.charAt(i)]++;
for(int i =0;i < s.length();i++){
if(--letterHash[s.charAt(i)] >= 0)
cnt++;
while(cnt == t.length()){
if(i - left + 1 < min_len){
min_len = i - left + 1;
ret = s.substring(left,left+min_len);
}
if(++letterHash[s.charAt(left)] > 0)
cnt--;
left++;
}
}
return ret;
}
}
思路:取自leetcode大神思路
- 遍历字符串
t
,将其字母出现次数以一次加1的方式记录在数组letterHash[]
- 遍历字符串
s
,将其出现的字母以一次减1的方式同样记录在数组中,如果减完了当前值还>=0
,说明当前字母s.charAt(i)
命中t中字母,cnt++
。 cnt
的长度代表当前s
中从left
到i已经命中的t中字母的长度,如果等于t
,则开始向右移动滑动窗口,以减小min_len
长度。- 如果当前
left~i
的长度小于min_len
,则更新min_lend
的长度和当前窗口的字符串ret
- 归还最左边的字母(
++letterHash[s.charAt(left)
),如果被移出去的字母在数组中的值大于0
,则证明被移出的字母之后当前窗口,缺少被移出的字母才能覆盖字符串t
,左移滑动窗口(left++
) - 继续遍历字符串
s
直至结束