LeetCode 76题是“最小覆盖子串”(Minimum Window Substring)。下面是一个Java解题的示例代码,并附上每行的注释。
import java.util.HashMap;
import java.util.Map;
public class Solution {
public String minWindow(String s, String t) {
if (s == null || t == null || s.length() < t.length()) {
return ""; // 如果s或t为空,或者s的长度小于t,则返回空字符串
}
// 记录t中每个字符的出现次数
Map<Character, Integer> map = new HashMap<>();
for (char c : t.toCharArray()) {
map.put(c, map.getOrDefault(c, 0) + 1);
}
int left = 0, right = 0; // 左右指针初始化
int count = map.size(); // 需要匹配的不同字符的数量
int minLen = Integer.MAX_VALUE; // 用于记录最小窗口长度
int minLeft = 0; // 记录最小窗口的起始位置
while (right < s.length()) {
char c = s.charAt(right); // 获取右指针当前字符
if (map.containsKey(c)) {
map.put(c, map.get(c) - 1); // 更新字符出现次数
if (map.get(c) == 0) {
count--; // 如果字符c的计数为0,减少待匹配的字符数量
}
}
right++; // 移动右指针
// 当所有字符匹配时,尝试缩小窗口
while (count == 0) {
if (right - left < minLen) { // 更新最小窗口
minLen = right - left;
minLeft = left;
}
char lc = s.charAt(left); // 获取左指针当前字符
if (map.containsKey(lc)) {
map.put(lc, map.get(lc) + 1); // 恢复字符lc的计数
if (map.get(lc) > 0) {
count++; // 如果字符lc的计数大于0,增加待匹配的字符数量
}
}
left++; // 移动左指针
}
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(minLeft, minLeft + minLen); // 返回最小覆盖子串
}
}
解题思路总结:
-
问题理解:
- 给定两个字符串
s和t,需要在s中找到最短的子串,该子串包含t中所有字符的排列。 - 如果
s中不存在这样的子串,则返回空字符串。
- 给定两个字符串
-
滑动窗口方法:
- 使用滑动窗口的技巧,这是一种用于处理子串或子数组问题的常用方法。
-
步骤概述:
-
初始化:
- 使用一个哈希表
map来记录字符串t中每个字符的出现次数。 - 定义两个指针
left和right表示当前窗口的左右边界。 - 使用一个变量
count来记录还需要匹配的不同字符的数量。 - 初始化最小窗口的长度
minLen和起始位置minLeft。
- 使用一个哈希表
-
扩展窗口:
- 移动
right指针以扩大窗口,逐个检查字符是否在t中。 - 如果字符在
t中,减少其在map中的计数。 - 如果某个字符的计数变为0,表示该字符已经完全匹配,减少
count。
- 移动
-
缩小窗口:
- 当
count为0时,表示当前窗口包含了所有t中的字符。 - 尝试移动
left指针缩小窗口,寻找更小的可行解。 - 每次缩小窗口时,检查并更新最小窗口的长度和起始位置。
- 当
-
返回结果:
- 如果找到了符合条件的窗口,返回最小窗口的子串;否则,返回空字符串。
-
-
复杂度:
- 时间复杂度为 O(n + m),其中 n 是字符串
s的长度,m 是字符串t的长度。 - 空间复杂度为 O(m),用于存储哈希表。
- 时间复杂度为 O(n + m),其中 n 是字符串
通过这种方法,可以有效地找到字符串 s 中包含 t 的最小覆盖子串。
337

被折叠的 条评论
为什么被折叠?



