2.3字节面试高频(力扣76. 最小覆盖子串)
题干: 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
-
对于
t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量。 -
如果
s中存在这样的子串,我们保证它是唯一的答案。 -
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC"
思路:此题应该使用滑动窗口方法来解答,下面给出思路:
s = "ADOBECODEBANC", t = "ABC"
此时窗口的左指针left和右指针right都为0,此时这个窗口中不含有t中的所有元素,右指针向右移动,直到右指针到达C[下标为5]的时候,
ADOBEC包含ABC,记录下此时的长度,因为要求的是最小的覆盖子串,所以left应该右移看是否有更小的;left到D不符合条件,
此时right应该右移,直到到达A[下标为10]的时候再次符合条件,记录长度,left右移直到left到达O[下标为6]不符合条件,
right右移到达C[最后一个],left调整到A,right右移,超出边界,退出循环;
代码:
class Solution {
public String minWindow(String s, String t) {
if(t.length() > s.length()) return "";
int[] om = new int[256];
int lent = t.length();
for (int i = 0; i < lent; i++) {
om[t.charAt(i)]++;
} //记录下t中的,每个字符字符的数量
int[] cm = new int[256];
int left = 0;
int right = 0;
int mLeft = 0;
int mRight = -1;
int min = Integer.MAX_VALUE;
for (; right < s.length(); right++) {
if (om[s.charAt(right)] > 0) { //如果这个字符t中有,cm也应该加一
cm[s.charAt(right)]++;
}
while (isE(om,cm)) { //当cm中包含om时
int m = right - left;
if (m < min) {
mLeft = left;
mRight = right;
min = m;
}
if (om[s.charAt(left)] > 0) {
cm[s.charAt(left)]--;
}
left++; //left右移
}
}
return s.substring(mLeft,mRight + 1);
}
public boolean isE(int[] om, int[] cm) { //如果数组om中的元素小于等于cm中的说明成立,放回true
for (int i = 0; i < om.length; i++) {
if (om[i] > cm[i]) {
return false;
}
}
return true;
}
}