描述
农场主有一群牛,每头牛都有一个独特的名字,名字由英文字母组成。农场主想要从这些牛的名字中选出一些牛,使得他们的名字中包含了所有的指定英文字母。你需要帮助农场主找出一个最短的名字序列,这个序列中的名字能够包含所有的指定英文字母。
示例1
输入:"ABCDEFGHIJKLMNOPQRSTUVWXYZ","XZ"
返回值:"XYZ"
示例2
输入:"ABCDEFGHIJKLMNOPQRSTUVWXYZ","ZZZZZZZZZZZZZZZZZZZZZZZZZZ"
返回值:""
备注:
输入:第一行是一个字符串s,表示所有牛的名字拼接起来的字符串。第二行是一个字符串t,表示指定的英文字母。
输出:返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。如果 s 中存在这样的子串,我们保证它是唯一的答案。
m == s.length,n == t.length,1 <= m, n <= 10^5,s 和 t 由英文字母组成
知识点
滑动窗口
解题思路
我们需要统计目标字母表t中每个字母出现的频率。然后,我们使用两个指针left和right来维护一个滑动窗口。
具体步骤如下:
- 初始化指针left和right为字符串s的起始位置。
- 移动指针right,扩展窗口,直到窗口中包含了所有目标字母表t中的字母。
- 记录当前窗口的长度和起始位置。
- 移动指针left,缩小窗口,直到窗口无法再排除目标字母表t中的字母。
- 重复步骤2-4,直到指针right到达字符串s的末尾。
Java题解
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @param t string字符串
* @return string字符串
*/
public String minWindow (String s, String t) {
// write code here
int[] targetFreq = new
int[128]; // 用于统计目标字母表t中每个字母的频率
for (char c : t.toCharArray()) {
targetFreq[c]++;
}
int[] windowFreq = new int[128]; // 用于统计窗口中每个字母的频率
int left = 0; // 窗口的左指针
int right = 0; // 窗口的右指针
int minLength = Integer.MAX_VALUE; // 最小窗口的长度
int start = 0; // 最小窗口的起始位置
int count = t.length(); // 窗口中包含的目标字母的总数
while (right < s.length()) {
char c = s.charAt(right);
windowFreq[c]++;
if (windowFreq[c] <= targetFreq[c]) {
count--;
}
while (count == 0) {
// 更新最小窗口的起始位置和长度
if (right - left + 1 < minLength) {
minLength = right - left + 1;
start = left;
}
char leftChar = s.charAt(left);
windowFreq[leftChar]--;
if (windowFreq[leftChar] < targetFreq[leftChar]) {
count++;
}
left++; // 缩小窗口
}
right++; // 扩展窗口
}
if (minLength == Integer.MAX_VALUE) {
return "";
}
return s.substring(start, start + minLength);
}
}