|
| 1 | +# Time Complexity: O(N) - go through the string with two pointers, so it's basically O(N). |
| 2 | +# Space Complexity: O(1) - only storing character frequencies (max 52 keys for a-z & A-Z), so it's effectively constant space. |
| 3 | + |
| 4 | +class Solution: |
| 5 | + def minWindow(self, s: str, t: str) -> str: |
| 6 | + # store character counts for t |
| 7 | + target_count = Counter(t) |
| 8 | + # window character count |
| 9 | + window_count = defaultdict(int) |
| 10 | + |
| 11 | + # start of the window |
| 12 | + left = 0 |
| 13 | + # min substring |
| 14 | + min_substring = "" |
| 15 | + # tracks how many characters match the required count |
| 16 | + matched_chars = 0 |
| 17 | + # unique characters needed |
| 18 | + required_chars = len(target_count) |
| 19 | + |
| 20 | + for right, char in enumerate(s): |
| 21 | + # expand window by adding the rightmost character |
| 22 | + if char in target_count: |
| 23 | + window_count[char] += 1 |
| 24 | + if window_count[char] == target_count[char]: |
| 25 | + matched_chars += 1 |
| 26 | + |
| 27 | + # try shrinking the window if all required characters are present |
| 28 | + while matched_chars == required_chars: |
| 29 | + # update min substring if this one is shorter |
| 30 | + if min_substring == "" or (right - left + 1) < len(min_substring): |
| 31 | + min_substring = s[left:right + 1] |
| 32 | + |
| 33 | + # remove leftmost character and move left pointer |
| 34 | + if s[left] in window_count: |
| 35 | + window_count[s[left]] -= 1 |
| 36 | + if window_count[s[left]] < target_count[s[left]]: |
| 37 | + matched_chars -= 1 |
| 38 | + left += 1 |
| 39 | + |
| 40 | + return min_substring |
0 commit comments