Leetcode第76题
题目:
- 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案。
思路:
- 我们可以用滑动窗口来解决这个问题。
- 由于字符串 t 要统计重复字符,所以可以用HashMap来保存 t 中的字符及个数,用另一个HashMap来动态存储滑动窗口中的有效字符(即t中出现过的字符)及个数,然后比较两个HashMap,找到最短的子字符串。
代码:
import java.util.HashMap;
import java.util.Map;
/*
* @lc app=leetcode.cn id=76 lang=java
*
* [76] 最小覆盖子串
*/
// @lc code=start
class Solution
{
public String minWindow(String s, String t)
{
// 动态的保存滑动窗口中的有效字符(t中包含的字符)及其个数
Map<Character, Integer> sMap = new HashMap<>();
// 保存t中的字符及其个数
Map<Character, Integer> tMap = new HashMap<>();
// 滑动窗口的左指针
int left = 0;
// 记录最优解的左边界
int ansLeft = 0;
// 临时保存map中的key
Character key;
// 临时保存map中的value
Integer value;
// 记录滑动窗口的最小长度,即最短的子序列
int minLen = Integer.MAX_VALUE;
// 首先把t字符串中所有字符都取出来,计算每个字符的个数,存放入map中
for (int i = 0; i < t.length(); i++)
{
key = t.charAt(i);
if (tMap.get(key) != null)
{
value = tMap.get(key);
tMap.put(key, value + 1);
}
else
{
tMap.put(key, 1);
}
}
// right为滑动窗口的右指针
for (int right = 0; right < s.length(); right++)
{
key = s.charAt(right);
// 如果右指针指向的字符是t中的某个字符,那么就把这个字符在sMap中加1
if (tMap.containsKey(key))
{
if (sMap.get(key) != null)
{
value = sMap.get(key);
sMap.put(key, value + 1);
}
else
{
sMap.put(key, 1);
}
}
// 比较滑动窗口sMap中的有效字符及个数是否 >= tMap中的字符个数
while (compareMap(sMap, tMap))
{
// 这里为了减少无效字符的判断次数,直接将左指针指向滑动窗口中的最左边的有效字符
key = s.charAt(left);
while (!tMap.containsKey(key))
{
left++;
key = s.charAt(left);
}
// while循环完,此时left指向的key是一个有效的字符
// 取一个最短的符合要求的子序列
if (minLen > right - left + 1)
{
minLen = right - left + 1;
ansLeft = left;
}
// 将left向左移动,缩小窗口的范围,判断是否仍然符合要求
value = sMap.get(key);
sMap.put(key, value - 1);
left++;
}
}
return minLen != Integer.MAX_VALUE ? s.substring(ansLeft, ansLeft + minLen) : "";
}
// compare two map
// 比较滑动窗口sMap中的有效字符及个数是否 >= tMap中的字符个数
public boolean compareMap(Map<Character, Integer> sMap, Map<Character, Integer> tMap)
{
Character key;
Integer value;
for (Map.Entry<Character, Integer> entry : tMap.entrySet())
{
key = entry.getKey();
value = entry.getValue();
if (sMap.containsKey(key) && sMap.get(key) >= value)
{
}
else
{
return false;
}
}
return true;
}
}
// @lc code=end