给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
拿到这道题目,先分析,从字符串S中找出包含T所有字符的最小子串,意思就是如果S里有T,那么再从S的子串里面找T,如果S里面没有T的话,那么S的子串里也不可能有T了。从大窗口滑到小窗口还是有点复杂的,不如反过来,由小窗口滑到大窗口来的简单一点。从小窗口滑到大窗口的话,就是这样的,如果小窗口内不包含T,则right++,直到窗口内包含T为止,若当right到到S的末尾还没有,即S没有T,则可以返回"",如果小窗口内包含T,那么将这个窗口的子串以及该子串的长度保存,然后left++,右移这个窗口,然后重复判断包不包含T的这个流程,然后记录子串的最小值以及对应的子串。
while left <= s.length() - t.length() //窗口长度小于T的长度的时候必不可能存在满足条件的子串
1 统计每个字符出现的次数
2 子串不包含T
right还未达到s的右边界
right++
right到达s的右边界
break
调整子串以及各个字符出现的次数
continue
子串包含T
left++
记录长度最小的子串和该子串的长度
调整子串以及各个字符出现的次数
总的来说核心的滑动窗口就是这样的了
public String minWindow(String s, String t) {
int[] tdic = new int[128 - 65];
int[] sdic = new int[128 - 65];
char[] dic = t.toCharArray();
String res = "";
int len = 0x7fffffff;
for (int i = 0; i < dic.length; i++) {
tdic[dic[i] - 65]++;
}
sdic[s.charAt(0) - 65] = 1;
int left = 0, right = 0;
int mark = 0;
int z = 0;
if (s.length() < t.length())
return "";
if (s.equals(t))
return s;
StringBuilder sb = new StringBuilder();
sb.append(s.charAt(left));
while (left <= s.length() - t.length()) {
mark = 0;
for (int i = 0; i < sdic.length; i++) {
if (tdic[i] > sdic[i]) {
mark = 1;
break;
}
}
if (mark == 1) {
if (right < s.length()) {
right++;
if (right == s.length())
break;
sb.append(s.charAt(right) );
sdic[s.charAt(right) - 65]++;
continue;
}
} else {
left++;
if(z++ == 0)
res = sb.length() < len ? sb.toString() : res;
else
res = sb.length() < res.length() ? sb.toString() : res;
sdic[s.charAt(left - 1) - 65]--;
sb.delete(0, 1);
}
}
return res;
}
不过在时间上,花的时间就很久,滑动策略有待优化,。。。
和咸咸打卡的第五天 √