public String minWindow(String s, String t) {
if (s == null || s.length() == 0 || t == null || t.length() == 0){
return "";
}
int[] need = new int[128];
//记录需要的字符的个数
for (int i = 0; i < t.length(); i++) {
need[t.charAt(i)]++; //128个字符,需要字符就在该位置+1
}
//l是当前左边界,r是当前右边界,size记录窗口大小(刚刚开始size无限大),count是需求的字符总个数,start是最小覆盖串开始的index
int l = 0, r = 0, size = Integer.MAX_VALUE, count = t.length(), start = 0;
//遍历所有字符
while (r < s.length()) {
char c = s.charAt(r);
if (need[c] > 0) {//需要字符c
count--; //需求的字符总个数-1
}
need[c]--;//把该字符加入窗口,如果该字符不是需要字符也加入窗口,把该字符的值-1,代表该字符多余
//如果该字符是需要字符也加入窗口,把该字符的值-1,代表该字符多余
if (count == 0) { //窗口中已经包含所有需要的字符
while (l < r && need[s.charAt(l)] < 0) { //左边有多余的字符
need[s.charAt(l)]++;//将该多余字符对应的值+1
l++;//左指针右移
}
if (r - l + 1 < size) {//不能右移时候挑战最小窗口大小,更新最小窗口开始的start
size = r - l + 1;
start = l;//记录下最小值时候的开始位置,最后返回覆盖串时候会用到
}
//此时l指向第一个最小窗口的最左边(没有多余元素),也就是需要的字符串中的第一个碰到的字符
//l向右移动后窗口肯定不能满足了 重新开始循环
//在l右移之前先把第一个需要的元素值+1,代表该元素后面需要一个
need[s.charAt(l)]++;
//l右移一个,重新开始循环
l++;
//需求的字符总个数+1
count++;
}
r++;
}
//size是否改变过,若size没有改变过则找不到满足题目要求的窗口
return size == Integer.MAX_VALUE ? "" : s.substring(start, start + size);
}
76.最小覆盖子串(带详细注释的Java版本)
于 2024-04-16 17:20:17 首次发布