算法题(程序员面试宝典)
解题思路主要来源于leetcode官方与《程序员面试宝典》。
76. 最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
示例 2:
输入:s = “a”, t = “a”
输出:“a”
提示:
1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?
解题方法
解题思路1
class Solution {
public String minWindow(String s, String t) {
//滑动窗口技巧(双指针思想)
//need:保存t中的字符:数量 {"A":1,"B":1}
//window:保存窗口中的符合t 中字符的 字符:数量 {"A":1,"B":2}
HashMap<Character,Integer> need = new HashMap<Character,Integer>();
HashMap<Character,Integer> window = new HashMap<Character,Integer>();
//need,window 初始化
for(int i=0;i<t.length();i++){
char c = t.charAt(i);
need.put(c,need.getOrDefault(c,0)+1);
}
for(int i=0;i<t.length();i++){
char c = t.charAt(i);
window.put(c,0);
}
//窗口的左右边界
int left,right;
left = right = 0;
//窗口中包含的t 中字符的个数(无重复)
int valid = 0;
//最小字串的起始位start, 最小字串的长度
int start = 0;
int len = Integer.MAX_VALUE;
//滑动窗口步骤
while(right<s.length()){
//扩大窗口
char c = s.charAt(right);
right++;
//更新window 内容
if(need.containsKey(c)){
//更新对应字符的数量
window.put(c,window.get(c)+1);
if(need.get(c).equals(window.get(c)))
valid++;
}
//当窗口中的字符 包含 t中字符 开始减小窗口
while(valid==need.size()){
//先记录 目前 子串的起始位置 和 长度
if(right-left<len){
start = left;
len = right-left;
}
//减小窗口
char d = s.charAt(left);
left++;
//更新window中内容
if(need.containsKey(d)){
if(need.get(d).equals(window.get(d)))
valid--;
window.put(d,window.get(d)-1);
}
}
}
return (len == Integer.MAX_VALUE)?"":s.substring(start,start+len);
}
}
最后一个测试用例一直过不了,因为定义的Map里的Integer是对象,Integer会缓存频繁使用的数值[-128,127],超过此范围就会new一个对象,导致使用“==”错误,改为equals()即可。
参考资料:https://leetcode-cn.com/problems/minimum-window-substring/solution/labuladongde-suan-fa-xiao-chao-javaban-b-glhm/
https://blog.csdn.net/losetowin/article/details/49968365