题目:
https://leetcode-cn.com/problems/minimum-window-substring/
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
示例:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”
说明:
如果 S 中不存这样的子串,则返回空字符串 “”。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
这道题的思路是使用双指针。前一个指针一直前移直到ss(两个指针内的字符串)包含t,后一个指针再前移,直到失败,依次往复。
在加上一些小技巧。
public String minWindow(String s, String t) {
int len = 'z' - 'A' + 1;
//字符数组,保存数组个数
int[] succ = new int[len];
for (int i = 0; i < t.length(); i++) {
succ[t.charAt(i) - 'A']++;
}
int sta = 0;
for (; sta < s.length(); sta++) {
int k = s.charAt(sta) - 'A';
succ[k]--;
if (succ[k] == 0 && allS(succ)) {
break;
}
}
if (sta == s.length()) {
return "";
}
//双指针,开始,结束
int staS = sta;
int endS = 0;
int end = 0;
boolean jin = false;
int min = staS - endS;
//因为一次只会更改一个数字,而当第一个1出现时,就会切换jin,所以,不用判断所有的数组
w:
while (true) {
if (jin) {
for (; sta < s.length(); sta++) {
int k = s.charAt(sta) - 'A';
succ[k]--;
//终于把这个1抓到了,你还是变回0吧,end指针,继续
if (succ[k] == 0) {
jin = false;
end++;
continue w;
}
}
break;
} else {
for (; end < sta; end++) {
int k = s.charAt(end) - 'A';
succ[k]++;
//有数字超过0,快快,sta指针,轮到你了
if (succ[k] == 1) {
//长度更短,记录
if (sta - end < min) {
min = sta - end;
staS = sta;
endS = end;
}
jin = true;
sta++;
continue w;
}
}
}
}
return s.substring(endS, staS + 1);
}
/**
* 如果所有的值都是不大于0的,说明t字符串被包含了
*/
private boolean allS(int[] succ) {
for (int i = 0; i < succ.length; i++) {
if (succ[i] > 0) {
return false;
}
}
return true;
}