Java算法题-解析 "最小覆盖子串" 算法问题
题目:
给定一个字符串 s
和一个字符串 t
,在字符串 s
中找出包含字符串 t
所有字符的最小子串。要求时间复杂度为 O(n)。
引言:
"最小覆盖子串" 是一个关于字符串处理和滑动窗口的问题。解决这个问题需要对字符串的滑动窗口和字符计数有一定的理解,同时需要找到一种方法来在窗口中找到最小子串。通过解答这个问题,我们可以提升对滑动窗口技巧的考虑,同时也能拓展对字符串处理的思路。
算法思路:
为了找到最小覆盖子串,我们可以使用滑动窗口的方法来进行操作。具体思路如下:
- 使用两个指针
left
和right
来构建一个滑动窗口,表示字符串s
中的子串。 - 初始化一个字符计数的映射,用于存储字符串
t
中每个字符出现的次数。 - 使用变量
count
来表示当前窗口中满足要求的字符数目。对于count
,我们只关心其中的正值。 - 移动右指针
right
,将窗口扩展,同时更新字符计数映射和count
。 - 当
count
达到t
中字符数目时,表示当前窗口满足条件。此时,我们可以尝试收缩左指针left
,找到包含所有字符的最小窗口。 - 重复步骤 4 和 5,直到右指针到达字符串末尾。
- 在过程中记录满足条件的最小窗口的长度和起始位置。
代码实现:
以下是使用 Java 实现的 "最小覆盖子串" 算法的示例代码:
import java.util.HashMap;
import java.util.Map;
public class MinimumWindowSubstring {
public String minWindow(String s, String t) {
Map<Character, Integer> targetCount = new HashMap<>();
for (char c : t.toCharArray()) {
targetCount.put(c, targetCount.getOrDefault(c, 0) + 1);
}
int left = 0;
int right = 0;
int minLen = Integer.MAX_VALUE;
int start = 0;
int count = t.length();
while (right < s.length()) {
char charRight = s.charAt(right);
if (targetCount.containsKey(charRight)) {
if (targetCount.get(charRight) > 0) {
count--;
}
targetCount.put(charRight, targetCount.get(charRight) - 1);
}
right++;
while (count == 0) {
if (right - left < minLen) {
minLen = right - left;
start = left;
}
char charLeft = s.charAt(left);
if (targetCount.containsKey(charLeft)) {
targetCount.put(charLeft, targetCount.get(charLeft) + 1);
if (targetCount.get(charLeft) > 0) {
count++;
}
}
left++;
}
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
}
}
算法分析:
- 时间复杂度:遍历字符串一次,所以时间复杂度为 O(n),其中 n 是字符串
s
的长度。 - 空间复杂度:使用了一个字符计数映射,所以空间复杂度为 O(k),其中 k 是字符串
t
中不同字符的数目。
示例和测试:
假设给定字符串 s = "ADOBECODEBANC"
和 t = "ABC"
,根据算法,最小覆盖子串为 "BANC"
。
我们可以使用以下代码进行测试:
public class Main {
public static void main(String[] args) {
MinimumWindowSubstring solution = new MinimumWindowSubstring();
String s = "ADOBECODEBANC";
String t = "ABC";
String minWindow = solution.minWindow(s, t);
System.out.println("Minimum window substring: " + minWindow);
}
}
总结:
"最小覆盖子串" 算法题要求在字符串中找到包含目标子串的最小子串,是一个关于滑动窗口和字符串处理的问题。通过实现这个算法,我们可以提升对滑动窗口技巧的考虑,同时也能拓展对字符串处理的思路。这个问题强调了如何使用滑动窗口来找到最小子串。