From 00b17c4c7c7243e28a6bd50c309fdb8eee53a6a9 Mon Sep 17 00:00:00 2001 From: Wilson Strasilla Date: Thu, 17 Oct 2024 13:03:14 -0700 Subject: [PATCH 1/8] Added an algorithm to the strings sub folder which finds the smallest substring of a given string which contains all of the characters in another given string. --- strings/min_window_substring.py | 87 +++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 strings/min_window_substring.py diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py new file mode 100644 index 000000000..9aa85cd2d --- /dev/null +++ b/strings/min_window_substring.py @@ -0,0 +1,87 @@ +def min_window(search_str: str, target_letters: str) -> str: + """ + Given a string to search, and another string of target char_dict, + return the smallest substring of the search string that contains + all target char_dict. + + >>> is_contains_unique_chars("Hello World", "lWl") + "llo W" + >>> is_contains_unique_chars("Hello World", "f") + "" + + This solution uses a sliding window, alternating between shifting + the end of the window right until all target char_dict are contained + in the window, and shifting the start of the window right until the + window no longer contains every target character. + + Time complexity: O(target_count + search_len) -> + The algorithm checks a dictionary at most twice for each character + in search_str. + + Space complexity: O(search_len) -> + The primary contributer to additional space is the building of a + dictionary using the search string. + """ + + target_count = len(target_letters) + search_len = len(search_str) + + + #Return if not possible due to string lengths. + if (search_len < target_count): + return "" + + #Build dictionary with counts for each letter in target_letters + char_dict = {} + for ch in target_letters: + if ch not in char_dict: + char_dict[ch] = 1 + else: + char_dict[ch] += 1 + + #Initialize window + window_start = 0 + window_end = 0 + + exists = False + min_window_len = search_len + 1 + + #Start sliding window algorithm + while(window_end < search_len): + + #Slide window end right until all search characters are contained + while(target_count > 0 and window_end < search_len): + cur = search_str[window_end] + if cur in char_dict: + char_dict[cur] -= 1 + if (char_dict[cur] >= 0): + target_count -= 1 + window_end += 1 + temp = window_end - window_start + + #Check if window is the smallest found so far + if (target_count == 0 and temp < min_window_len): + min_window = [window_start,window_end] + exists = True + min_window_len = temp + + #Slide window start right until a search character exits the window + while(target_count == 0 and window_start < window_end): + cur = search_str[window_start] + window_start += 1 + if cur in char_dict: + char_dict[cur] += 1 + if (char_dict[cur] > 0): + break + temp = window_end - window_start + 1 + + #Check if window is the smallest found so far + if (temp < min_window_len and target_count == 0): + min_window = [window_start-1,window_end] + min_window_len = temp + target_count = 1 + + if (exists): + return search_str[min_window[0]:min_window[1]] + else: + return "" \ No newline at end of file From 7fc42c79f02ecddd5f3dd9a6e0fc54afbd7e2cbd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 21:20:00 +0000 Subject: [PATCH 2/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- strings/min_window_substring.py | 54 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py index 9aa85cd2d..c2bdf58ef 100644 --- a/strings/min_window_substring.py +++ b/strings/min_window_substring.py @@ -14,24 +14,23 @@ def min_window(search_str: str, target_letters: str) -> str: in the window, and shifting the start of the window right until the window no longer contains every target character. - Time complexity: O(target_count + search_len) -> - The algorithm checks a dictionary at most twice for each character + Time complexity: O(target_count + search_len) -> + The algorithm checks a dictionary at most twice for each character in search_str. - Space complexity: O(search_len) -> - The primary contributer to additional space is the building of a + Space complexity: O(search_len) -> + The primary contributer to additional space is the building of a dictionary using the search string. """ - + target_count = len(target_letters) search_len = len(search_str) - - #Return if not possible due to string lengths. - if (search_len < target_count): + # Return if not possible due to string lengths. + if search_len < target_count: return "" - #Build dictionary with counts for each letter in target_letters + # Build dictionary with counts for each letter in target_letters char_dict = {} for ch in target_letters: if ch not in char_dict: @@ -39,49 +38,48 @@ def min_window(search_str: str, target_letters: str) -> str: else: char_dict[ch] += 1 - #Initialize window + # Initialize window window_start = 0 window_end = 0 exists = False min_window_len = search_len + 1 - #Start sliding window algorithm - while(window_end < search_len): - - #Slide window end right until all search characters are contained - while(target_count > 0 and window_end < search_len): + # Start sliding window algorithm + while window_end < search_len: + # Slide window end right until all search characters are contained + while target_count > 0 and window_end < search_len: cur = search_str[window_end] if cur in char_dict: char_dict[cur] -= 1 - if (char_dict[cur] >= 0): + if char_dict[cur] >= 0: target_count -= 1 window_end += 1 temp = window_end - window_start - #Check if window is the smallest found so far - if (target_count == 0 and temp < min_window_len): - min_window = [window_start,window_end] + # Check if window is the smallest found so far + if target_count == 0 and temp < min_window_len: + min_window = [window_start, window_end] exists = True min_window_len = temp - #Slide window start right until a search character exits the window - while(target_count == 0 and window_start < window_end): + # Slide window start right until a search character exits the window + while target_count == 0 and window_start < window_end: cur = search_str[window_start] window_start += 1 if cur in char_dict: char_dict[cur] += 1 - if (char_dict[cur] > 0): + if char_dict[cur] > 0: break temp = window_end - window_start + 1 - #Check if window is the smallest found so far - if (temp < min_window_len and target_count == 0): - min_window = [window_start-1,window_end] + # Check if window is the smallest found so far + if temp < min_window_len and target_count == 0: + min_window = [window_start - 1, window_end] min_window_len = temp target_count = 1 - if (exists): - return search_str[min_window[0]:min_window[1]] + if exists: + return search_str[min_window[0] : min_window[1]] else: - return "" \ No newline at end of file + return "" From 3418c8031f16a602875e59ab44b2609463bfe672 Mon Sep 17 00:00:00 2001 From: Wilson Strasilla Date: Thu, 17 Oct 2024 14:35:45 -0700 Subject: [PATCH 3/8] Formatting Fixes --- strings/min_window_substring.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py index 9aa85cd2d..396526f9e 100644 --- a/strings/min_window_substring.py +++ b/strings/min_window_substring.py @@ -14,15 +14,15 @@ def min_window(search_str: str, target_letters: str) -> str: in the window, and shifting the start of the window right until the window no longer contains every target character. - Time complexity: O(target_count + search_len) -> - The algorithm checks a dictionary at most twice for each character + Time complexity: O(target_count + search_len) -> + The algorithm checks a dictionary at most twice for each character in search_str. - Space complexity: O(search_len) -> - The primary contributer to additional space is the building of a + Space complexity: O(search_len) -> + The primary contributer to additional space is the building of a dictionary using the search string. """ - + target_count = len(target_letters) search_len = len(search_str) @@ -84,4 +84,4 @@ def min_window(search_str: str, target_letters: str) -> str: if (exists): return search_str[min_window[0]:min_window[1]] else: - return "" \ No newline at end of file + return "" From d11acec5f33ade7381aecbf05fd3306c43919304 Mon Sep 17 00:00:00 2001 From: Wilson Strasilla Date: Thu, 17 Oct 2024 15:16:28 -0700 Subject: [PATCH 4/8] Fixed a spelling issue --- strings/min_window_substring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py index c2bdf58ef..f7985654f 100644 --- a/strings/min_window_substring.py +++ b/strings/min_window_substring.py @@ -19,7 +19,7 @@ def min_window(search_str: str, target_letters: str) -> str: in search_str. Space complexity: O(search_len) -> - The primary contributer to additional space is the building of a + The primary contributor to additional space is the building of a dictionary using the search string. """ From deb7f89291d4326711695d469db12a600a486fbf Mon Sep 17 00:00:00 2001 From: Wilson Strasilla Date: Thu, 17 Oct 2024 15:24:12 -0700 Subject: [PATCH 5/8] Fixed incorrect function name in test cases --- strings/min_window_substring.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py index f7985654f..5441d2684 100644 --- a/strings/min_window_substring.py +++ b/strings/min_window_substring.py @@ -4,9 +4,9 @@ def min_window(search_str: str, target_letters: str) -> str: return the smallest substring of the search string that contains all target char_dict. - >>> is_contains_unique_chars("Hello World", "lWl") + >>> min_window("Hello World", "lWl") "llo W" - >>> is_contains_unique_chars("Hello World", "f") + >>> min_window("Hello World", "f") "" This solution uses a sliding window, alternating between shifting From 85fcd387ccff8ff8d76af47a4a0ede4fa13f8164 Mon Sep 17 00:00:00 2001 From: Wilson Strasilla Date: Thu, 17 Oct 2024 15:28:24 -0700 Subject: [PATCH 6/8] Fixed incorrect function name in test cases --- strings/min_window_substring.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py index 5441d2684..d19ff433c 100644 --- a/strings/min_window_substring.py +++ b/strings/min_window_substring.py @@ -5,9 +5,9 @@ def min_window(search_str: str, target_letters: str) -> str: all target char_dict. >>> min_window("Hello World", "lWl") - "llo W" + 'llo W' >>> min_window("Hello World", "f") - "" + '' This solution uses a sliding window, alternating between shifting the end of the window right until all target char_dict are contained @@ -28,7 +28,7 @@ def min_window(search_str: str, target_letters: str) -> str: # Return if not possible due to string lengths. if search_len < target_count: - return "" + return '' # Build dictionary with counts for each letter in target_letters char_dict = {} @@ -82,4 +82,4 @@ def min_window(search_str: str, target_letters: str) -> str: if exists: return search_str[min_window[0] : min_window[1]] else: - return "" + return '' From 43993fb763b9986d6405963267a582091a0e8a07 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 22:28:56 +0000 Subject: [PATCH 7/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- strings/min_window_substring.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py index d19ff433c..d241bdc3f 100644 --- a/strings/min_window_substring.py +++ b/strings/min_window_substring.py @@ -28,7 +28,7 @@ def min_window(search_str: str, target_letters: str) -> str: # Return if not possible due to string lengths. if search_len < target_count: - return '' + return "" # Build dictionary with counts for each letter in target_letters char_dict = {} @@ -82,4 +82,4 @@ def min_window(search_str: str, target_letters: str) -> str: if exists: return search_str[min_window[0] : min_window[1]] else: - return '' + return "" From 0ceeb2ccec6793fc77c8ad46e2d2a63e614728c8 Mon Sep 17 00:00:00 2001 From: Wilson Strasilla Date: Thu, 17 Oct 2024 15:39:21 -0700 Subject: [PATCH 8/8] Added link to leetcode. --- strings/min_window_substring.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/strings/min_window_substring.py b/strings/min_window_substring.py index d19ff433c..2994bb776 100644 --- a/strings/min_window_substring.py +++ b/strings/min_window_substring.py @@ -4,6 +4,10 @@ def min_window(search_str: str, target_letters: str) -> str: return the smallest substring of the search string that contains all target char_dict. + This is somewhat modified from my solution to the problem + "Minimum Window Substring" on leetcode. + https://leetcode.com/problems/minimum-window-substring/description/ + >>> min_window("Hello World", "lWl") 'llo W' >>> min_window("Hello World", "f")