掘金团队号上线,助你 Offer 临门! 点击 查看大厂春招职位
一、题目描述:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
题目地址:leetcode-cn.com/problems/mi…
二、思路分析:
滑动窗口 + HashMap。 首先统计 t 里字符出现的次数。然后使用双指针,遍历 s, 先扩展窗口,右侧指针右移,直到包含所有 t中的字符。
然后缩放窗口,左侧指针右移。直到不能再删除。找到一个答案。
每找到一个答案与之前的答案比较,取长度较小的结果。
更新完答案后,左侧指针右移一次,然后再次扩展窗口,右侧指针不断右移,直到再次找到一个答案。
三、AC 代码:
public static String minWindow(String s, String t) {
Map<Character, Integer> tMap = new HashMap<>();
if (s.length() == 0 || s.length() < t.length()) {
return "";
}
for (Character c : t.toCharArray()) {
if (tMap.containsKey(c)) {
tMap.put(c, tMap.get(c) + 1);
} else {
tMap.put(c, 1);
}
// s 中不包含 t 中的某个字符
if (s.indexOf(c) == -1) {
return "";
}
}
int end = 0;
int start = 0;
int count = tMap.size();
String ans = s+" ";
for (char c : s.toCharArray()) {
end++;
if (tMap.containsKey(c)) {
tMap.put(c, tMap.get(c) - 1);
if (tMap.get(c) == 0) {
count--;
}
}
if (count != 0) {
continue;
}
//找到一个结果,窗口左侧收缩
while (true) {
if (tMap.containsKey(s.charAt(start))) {
if (tMap.get(s.charAt(start)) == 0) {
System.out.println("ans-t:"+ans);
ans = s.substring(start, end).length() < ans.length() ? s.substring(start, end) : ans;
tMap.put(s.charAt(start), tMap.get(s.charAt(start)) + 1);
start++;
count++;
break;
}
tMap.put(s.charAt(start), tMap.get(s.charAt(start)) + 1);
}
start++;
}
}
return ans.length() <= s.length() ? ans : "";
四、总结
应该是还有其他更优的解法