题目链接:76. 最小覆盖子串
思路
这道题的目的是找s中最短窗口的子串,这个子串要包含t中的所有字符,这个题可以使用滑动窗口来做。
题的难点在于:如何判断当前s的窗口,是否包含t中所有字符
解决方式 :题目说明了s 和 t 由英文字母组成,所以我们可以创建cnt数组统计字符个数,然后可以用枚举的方式来做判断。具体方式见下面的isCovered方法
代码
java
class Solution {
public String minWindow(String S, String t) {
/**
* 找s中包含t的最短窗口
* 拆开:1.判断是否包含 2.是否最短
*/
//创建统计s跟t的个数的数组
int [] cntS = new int[128];
int [] cntT = new int[128];
//统计t的所有字母以及个数
for(char c : t.toCharArray()) {
cntT[c]++;
}
char [] s = S.toCharArray();
int m = s.length;
//滑动窗口,枚举left
int ansLeft = -1;
int ansRight = m;
int left = 0;
for(int right = 0; right < m; right++) {
cntS[s[right]]++;
while(isCovered(cntS,cntT)) {
//查看当前的窗口是否更小
if(right - left < ansRight - ansLeft) {
ansRight = right;
ansLeft = left;
}
cntS[s[left]]--;
left++;
}
}
return ansLeft < 0 ? "" : S.substring(ansLeft,ansRight+1);
}
private boolean isCovered(int [] cntS,int [] cntT) {
for(int c = 'a'; c <= 'z'; c++) {
if(cntS[c] < cntT[c]) {
return false;
}
}
for(int c = 'A'; c <= 'Z'; c++) {
if(cntS[c] < cntT[c]) {
return false;
}
}
return true;
}
}
时间复杂度分析
-
初始化
cntT,遍历符串t,时间复杂度是O(n) -
for循环
right循环,执行m次,时间复杂度是O(m) -
while循环当中,left最多移动m次,时间复杂度是O(m) -
isCovered方法遍历的是字符集(A-Z, a-z),共 52 次,所以isCovered方法本身的复杂度是O(1) -
isCovered总调用次数最多是2m次,所以总的时间复杂度是O(m) -
综上分析总的时间复杂度是
O(m+n)
注意
- 滑动窗口中两个指针各自单向遍历一次
- 千万不要认为嵌套循环就一定是O(m^2)
如果这篇文章对你有帮助,欢迎点赞、评论、关注、收藏。你们的支持是我前进的动力!