用i
和j
表示滑动窗口的左边界和右边界,思路如下:
j
右移,直到i-j
内包含住了t
的所有元素i
右移,去除掉左边多余元素- 保留最小长度,同时
i
右移,此时确定i-j
的子串一定不能完全覆盖t
,于是重复1,2,3步骤。
使用need
的HashMap
来记录覆盖t
中每个元素的所需个数。
为减少复杂度,使用needCount
来判断是否已经完全覆盖t
。
注意,need.get(c)
有可能小于0,这表示s
中c
的个数多于t
中c
的个数。
class Solution {
public String minWindow(String s, String t) {
String ans = "";
if (t.length() > s.length()) return ans;
HashMap<Character, Integer> need = new HashMap<>();
for (int i = 0; i < t.length(); ++i) {
char c = t.charAt(i);
need.put(c, need.getOrDefault(c, 0) + 1);
}
int left = 0;
int minLeft = 0, minLen = Integer.MAX_VALUE;
int needCount = t.length();
for (int right = 0; right < s.length(); ++right) {
char c = s.charAt(right);
if (need.containsKey(c)) {
need.put(c, need.get(c) - 1);
// needCount--;
if (need.get(c) >= 0) needCount--;
}
while (needCount == 0) {
if (right - left + 1 < minLen) {
minLeft = left;
minLen = right - left + 1;
}
char leftChar = s.charAt(left);
if (need.containsKey(leftChar)) {
need.put(leftChar, need.get(leftChar) + 1);
// needCount++;
if (need.get(leftChar) > 0) needCount++;
}
left++;
}
}
return minLen == Integer.MAX_VALUE ? ans : s.substring(minLeft, minLeft + minLen);
}
}