目录
- 解题思路与实现 - 最小覆盖子串
- 问题描述
- 示例
- 解题思路
- 算法实现
- 复杂度分析
- 测试与验证
- 总结
- 感谢阅读!
解题思路与实现 - 最小覆盖子串
问题描述
给定一个字符串 s
和一个字符串 t
,返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
示例
- 输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
解释:最小覆盖子串 “BANC” 包含来自字符串t
的 ‘A’、‘B’ 和 ‘C’。 - 输入:s = “a”, t = “a”
输出:“a”
解释:整个字符串s
是最小覆盖子串。 - 输入:s = “a”, t = “aa”
输出:“”
解释:t
中两个字符 ‘a’ 均应包含在s
的子串中,因此没有符合条件的子字符串,返回空字符串。
解题思路
使用滑动窗口(双指针)和哈希表的方法解决该问题:
- 使用哈希表
targetCount
记录字符串t
中每个字符的出现次数。 - 使用两个指针
left
和right
维护滑动窗口,初始时两者都指向字符串开头。 - 遍历字符串
s
,右指针right
向右移动,将字符加入窗口,并更新窗口内字符的计数。 - 当窗口包含了
t
中所有字符且满足条件时,移动左指针left
缩小窗口,尝试找到最小的覆盖子串。 - 更新最小覆盖子串的起始位置和长度。
算法实现
public String minWindow(String s, String t) {
if (s == null || s.isEmpty() || t == null || t.isEmpty() || s.length() < t.length()) {
return "";
}
// 统计 t 中每个字符的出现次数
Map<Character, Integer> targetCount = new HashMap<>();
for (char c : t.toCharArray()) {
targetCount.put(c, targetCount.getOrDefault(c, 0) + 1);
}
int left = 0, right = 0;
int minLen = Integer.MAX_VALUE;
int start = 0;
int requiredChars = targetCount.size(); // 需要覆盖的字符种类数
int formed = 0; // 已经覆盖的字符种类数
Map<Character, Integer> windowCount = new HashMap<>();
while (right < s.length()) {
char currentChar = s.charAt(right);
windowCount.put(currentChar, windowCount.getOrDefault(currentChar, 0) + 1);
if (targetCount.containsKey(currentChar) && windowCount.get(currentChar).intValue() == targetCount.get(currentChar).intValue()) {
formed++;
}
// 尝试缩小窗口
while (left <= right && formed == requiredChars) {
int currentLen = right - left + 1;
if (currentLen < minLen) {
minLen = currentLen;
start = left;
}
char leftChar = s.charAt(left);
windowCount.put(leftChar, windowCount.get(leftChar) - 1);
if (targetCount.containsKey(leftChar) && windowCount.get(leftChar).intValue() < targetCount.get(leftChar).intValue()) {
formed--;
}
left++;
}
right++;
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
}
复杂度分析
- 时间复杂度:O(m + n),其中
m
是字符串s
的长度,n
是字符串t
的长度。 - 空间复杂度:O(m + n),使用了两个哈希表来存储字符出现次数。
测试与验证
设计不同测试用例,包括空字符串、单个字符、多个字符等情况,验证算法的正确性和效率。
总结
通过本文的详细解题思路和算法实现,可以有效地解决给定字符串中涵盖指定字符集合的最小子串问题。利用滑动窗口和哈希表的方法,可以高效地实现该算法。
感谢阅读!