|
| 1 | +# 76. Minimum Window Substring |
| 2 | + |
| 3 | +## Two Pointer with Map Solution |
| 4 | +- Runtime: O(S * T) |
| 5 | +- Space: O(S) |
| 6 | +- S = Number of characters in string S |
| 7 | +- T = Number of unique characters in string T |
| 8 | + |
| 9 | +So the definition of a result requires the substring to contain all characters in T. It then wants the smallest substring. |
| 10 | +With that, we have to begin the solution by finding the first instance of that substring. |
| 11 | +Once we have that, we need to basically prune it, remove the extra characters from this substring to get the minimum substring. |
| 12 | +Finally, we keep repeating this until we reach the end. |
| 13 | +We can traverse the string via. two pointers, a left and right iterator. |
| 14 | +Right is bound within the given string S and left is bound within the substring created by the right pointer. |
| 15 | + |
| 16 | +To figure out if we have all the characters in this substring, we would have to count T via. a dictionary. |
| 17 | +This is our known count that is required for each substring. |
| 18 | +Then we have to keep a dynamic counter, decrementing and incrementing character counts as we move across the string. |
| 19 | +With this, after we moved the right pointer to the right, we can use these two dictionaries to check if this is a substring that meets the requirements. |
| 20 | +If so, we can then try pruning with the left pointer all the way to the right pointer or if it doesn't meet the requirement. |
| 21 | + |
| 22 | +You may think that the run-time for this is exponential, especially when we are checking the two dictionaries. |
| 23 | +However, don't be mistaken, the comparison is actually a constant T run-time, it doesn't change based on S, but rather on T. |
| 24 | +There is one slight problem, python's implementation of string concatention is actually O(N). |
| 25 | +When the question wants the actual substring and not a count, even using a deque will not solve this problem. |
| 26 | +So this implementation is technically O(S * (S+T)) due to python, but in other languages |
| 27 | + |
| 28 | +When implementing these type of two pointer questions. |
| 29 | +I recommend to avoid using indexes as much as possible and use iterators. |
| 30 | +It is very easy to get a one off error doing these and within a 30 minute timeframe, it is very risky. |
| 31 | + |
| 32 | +``` |
| 33 | +from collections import defaultdict |
| 34 | +from collections import Counter |
| 35 | +
|
| 36 | +class Solution: |
| 37 | + def minWindow(self, s: str, t: str) -> str: |
| 38 | + all_ch_counts = Counter(t) |
| 39 | + ch_to_n_counts = defaultdict(int) |
| 40 | + str_builder, min_substr, found = '', s, False |
| 41 | + for curr_right in s: |
| 42 | + ch_to_n_counts[curr_right] += 1 |
| 43 | + str_builder += curr_right |
| 44 | + if chars_occur_ge(ch_to_n_counts, all_ch_counts): |
| 45 | + for curr_left in str_builder: |
| 46 | + if chars_occur_ge(ch_to_n_counts, all_ch_counts): |
| 47 | + found = True |
| 48 | + if len(str_builder) < len(min_substr): |
| 49 | + min_substr = str_builder |
| 50 | + else: |
| 51 | + break |
| 52 | + ch_to_n_counts[curr_left] -= 1 |
| 53 | + str_builder = str_builder[1:] |
| 54 | + return min_substr if found else '' |
| 55 | + |
| 56 | +def chars_occur_ge(ch_to_n_counts, all_ch_counts): |
| 57 | + for ch, count in all_ch_counts.items(): |
| 58 | + if ch not in all_ch_counts or ch_to_n_counts[ch] < count: |
| 59 | + return False |
| 60 | + return True |
| 61 | +``` |
0 commit comments