You are given two strings: a source string s and a target string t. Your task is to find the shortest contiguous substring within s that contains every character from t, including duplicates. If multiple substrings of the same minimum length exist, return any one of them. If no such substring exists, return an empty string.
The substring must contain at least the same frequency of each character as appears in t. For example, if t contains two 'a's, the result substring must also contain at least two 'a's.
s that contains all characters from t with their required frequencies""tt ≤ length of s ≤ 100,000s and t consist of uppercase and lowercase English letterss and tExample 1:
Input: s = "ADOBECODEBANC", t = "ABC" Output: "BANC" Explanation: The substring "BANC" contains A, B, and C. Other substrings like "ADOBEC" also work but are longer.
Example 2:
Input: s = "a", t = "aa" Output: "" Explanation: The source string only has one 'a', but we need two. No valid window exists.
Example 3:
Input: s = "aaabbbc", t = "aabc" Output: "aabbc" Explanation: We need at least 2 a's, 1 b, and 1 c. The shortest window is "aabbc" with length 5.
Hint 1: Sliding Window Technique Consider using two pointers to represent a window in the source string. Expand the right pointer to include characters, and contract the left pointer when you have a valid window. This allows you to explore all possible windows efficiently.
Hint 2: Character Frequency Tracking Use hash maps (dictionaries) to track the frequency of characters needed from the target string and the frequency of characters in your current window. You can also maintain a counter to track how many unique characters have met their required frequency.
Hint 3: Optimization Strategy When your window contains all required characters, try shrinking it from the left to find the minimum length. Only move the right pointer when the window becomes invalid. Keep track of the smallest valid window seen so far.
Full Solution `` Approach Explanation:
This solution uses the sliding window technique combined with frequency counting:
- Initialization: Create a frequency map for the target string to know what characters and counts we need. Initialize two pointers (left and right) to represent our window.
- Expand Phase: Move the right pointer to expand the window, adding characters to our window frequency map. Track when each unique character reaches its required frequency.
- Contract Phase: Once all required characters are in the window with sufficient frequency, try shrinking from the left to find the minimum valid window. Update the result whenever we find a smaller valid window.
- Tracking State: Use
formed_charsto efficiently track when we have a valid window (all unique characters meet their frequency requirement) instead of comparing entire maps each time.Time Complexity: O(m + n) where m is the length of
sand n is the length oft. Each character insis visited at most twice (once by right pointer, once by left pointer).Space Complexity: O(k) where k is the number of unique characters in
t(at most 52 for English letters, or 128 for ASCII). We store frequency maps for target and window characters.
def minWindow(s: str, t: str) -> str:
# Edge case: if t is longer than s, no solution exists
if len(t) > len(s):
return ""
# Build frequency map for target string
target_freq = {}
for char in t:
target_freq[char] = target_freq.get(char, 0) + 1
# Track how many unique characters we need to match
required_chars = len(target_freq)
formed_chars = 0 # How many unique characters currently meet the frequency requirement
# Window frequency map
window_freq = {}
# Pointers for the sliding window
left = 0
min_len = float('inf')
min_window_start = 0
# Expand the window with the right pointer
for right in range(len(s)):
char = s[right]
window_freq[char] = window_freq.get(char, 0) + 1
# Check if this character's frequency matches the requirement
if char in target_freq and window_freq[char] == target_freq[char]:
formed_chars += 1
# Try to contract the window from the left while it's still valid
while formed_chars == required_chars and left <= right:
# Update result if this window is smaller
window_len = right - left + 1
if window_len < min_len:
min_len = window_len
min_window_start = left
# Remove the leftmost character and shrink the window
left_char = s[left]
window_freq[left_char] -= 1
# Check if removing this character breaks the requirement
if left_char in target_freq and window_freq[left_char] < target_freq[left_char]:
formed_chars -= 1
left += 1
# Return the minimum window or empty string if none found
return "" if min_len == float('inf') else s[min_window_start:min_window_start + min_len]