Solution: sliding window O(∣S∣+∣T∣)
-
t may include duplicates, so we need to count frequency of t
-
Expand right pointer r to include characters
-
Shrink left pointer l or left to minimize the window
-
track # of UNIQUE char in cur window meets requirement
- requirements: 1. present in t 2. frequency
-
Track best (smallest) valid window at current step
class Solution {
public String minWindow(String s, String t) {
// frequency of each char in t
Map<Character, Integer> tFreq = new HashMap<>();
for (char c : t.toCharArray()) {
tFreq.put(c, tFreq.getOrDefault(c, 0) + 1);
}
// to track the frequency of char in window
Map<Character, Integer> windowFreq = new HashMap<>();
// # of UNIQUE char in cur window meets requirement
// requirements: 1. present in t 2. frequency
int count = 0;
// for result
int minLen = Integer.MAX_VALUE, minStart = -1, minEnd = -1;
int left = 0, right = 0;
while (left < s.length() && right < s.length()) {
// Expand window via right ++
char cur = s.charAt(right);
windowFreq.put(cur, windowFreq.getOrDefault(cur, 0) + 1);
// if uses ==, which is risky for boxed Integer objects (especially outside the [-128, 127] range).
if (tFreq.containsKey(cur) && windowFreq.get(cur).intValue() == tFreq.get(cur).intValue()) {
count++;
}
// Contract window size via left++
while (count == tFreq.size()) {
// best result currently
if (right - left + 1 < minLen) {
minStart = left;
minEnd = right;
minLen = Math.min(minLen, right - left + 1);
}
char c = s.charAt(left);
windowFreq.put(c, windowFreq.get(c) - 1);
if (tFreq.containsKey(c)) {
if (windowFreq.get(c).intValue() < tFreq.get(c).intValue()) {
count--;
}
}
left++; // contract
}
right++; // expand
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minEnd + 1);
}
}