题目:给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案
示例1
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例2
输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。
示例3
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
题目来源:力扣(LeetCode) 链接
解题模板(出自labuladong)
/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
Map<Character, Integer> need = new HashMap<>();
Map<Character, Integer> window = new HashMap<>();
for (char c : t.toCharArray())
need.put(c,need.getOrDefault(c,0)+1);
int left = 0, right = 0;
int valid = 0;
while (right < s.size()) {
// c 是将移入窗口的字符
char c = s.charAt(right);
// 右移窗口
right++;
// 进行窗口内数据的一系列更新
...
/*** debug 输出的位置 ***/
System.out.println("window: ["+left+","+ right+")");
/********************/
// 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 左移窗口
left++;
// 进行窗口内数据的一系列更新
...
}
}
}
题解
class Solution {
public String minWindow(String s, String t) {
//定义一个map以键值对的方式存放t中的每一个字符以及对应的个数
Map<Character, Integer> need = new HashMap<>();
//定义一个map存放窗口中对应的字符和字符个数
Map<Character, Integer> window = new HashMap<>();
//把字符串t中的字符和对应的个数保存到map中
for(char c : t.toCharArray()) {
//getOrDefault(key,default)函数作用:
//如果存在key,就返回对应的value,否则返回默认值
need.put(c, getOrDefault(c, 0) + 1);
}
int left = 0;//定义左指针
int right = 0;//定义右指针
//count用来记录窗口中的字符个数是否满足需要,如果有一个字符满足,count++
int count = 0;
int start = 0;//用来记录满足要求的子串的起始位置
//len用来记录满足要求的子串的长度,每次都与len比较,选出来最小的
int len = Interget.MAX_VALUE;
while (right < s.length()) { //更新窗口
char c = s.toCharAt(right);
right++;
if (need.containsKey(c)) { //判断取出的字符是否是need需要的
//如果需要,就把该字符和个数放入到window中
window.put(c, getOrDefault(c, 0) + 1);
//如果window中的c字符个数满足要求,就记录下来
if (need.get(c) == window.get(c)) {
count++;
}
}
//count == need.size()说明此时子串满足要求,所以开始收缩窗口
while (count == need.size()) {
//如果此时子串长度更小就更新len,并且更新子串的起始位置
if (right - left < len) {
len = right - left;
start = left;
}
//从子串最左侧开始取出字符(收缩窗口)
char d = s.toCharAt(left);
left++;
//判断need中是否存在该字符
if (need.containsKey(d)) {
//先判断此时need中该字符的数量是否和window中的相等,相等就count--
if (need.get(d) == window.get(d)) {
count--;
}
//每次都要先判断再把window中对应的字符数量减1
window.put(d, window.get(d) - 1);
}
}
}
//如果len不等于原来的值说明找到了,就返回对应子串,否则返回空串
return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
}
}
标签:子串,字符,right,笔记,76,window,need,left
From: https://www.cnblogs.com/benben-home/p/17209254.html