diff --git a/grind75_hard/01_76_Minimum Window Substring/level_1.py b/grind75_hard/01_76_Minimum Window Substring/level_1.py new file mode 100644 index 0000000..7b0fbe9 --- /dev/null +++ b/grind75_hard/01_76_Minimum Window Substring/level_1.py @@ -0,0 +1,31 @@ +# ポインタを2つ使い条件を満たす範囲を見つける。 +# まずtの文字全てが含まれるwindowを見つけるために、rightを進めていく +# tの文字全てが含まれるwindowを見つけたら、leftを進めて無駄な文字を削除していく +class Solution: + def minWindow(self, s: str, t: str) -> str: + t_count = defaultdict(int) + for c in t: + t_count[c] += 1 + window_count = defaultdict(int) + left = 0 + right = 0 + match_num = 0 + min_length = math.inf, None, None + while right < len(s): + if s[right] in t_count: + window_count[s[right]] += 1 + if window_count[s[right]] == t_count[s[right]]: + match_num += 1 + while left <= right and match_num == len(t_count): + if min_length[0] > right - left: + min_length = right - left, left, right + if s[left] in t_count: + window_count[s[left]] -= 1 + if window_count[s[left]] < t_count[s[left]]: + match_num -= 1 + left += 1 + right += 1 + if min_length[0] == math.inf: + return "" + _, left, right = min_length + return s[left : right + 1] diff --git a/grind75_hard/01_76_Minimum Window Substring/level_2.py b/grind75_hard/01_76_Minimum Window Substring/level_2.py new file mode 100644 index 0000000..f2780b4 --- /dev/null +++ b/grind75_hard/01_76_Minimum Window Substring/level_2.py @@ -0,0 +1,29 @@ +# rightをfor文で実装 +# 最小のwindowのindexのみを保持するように修正 +class Solution: + def minWindow(self, s: str, t: str) -> str: + t_count = defaultdict(int) + for c in t: + t_count[c] += 1 + left = 0 + match_num = 0 + window_count = defaultdict(int) + min_window_index = (left, math.inf) + for right, c in enumerate(s): + if c not in t_count: + continue + window_count[c] += 1 + if window_count[c] == t_count[c]: + match_num += 1 + while left <= right and match_num == len(t_count): + if right - left + 1 < min_window_index[1] - min_window_index[0] + 1: + min_window_index = (left, right) + if s[left] in t_count: + window_count[s[left]] -= 1 + if window_count[s[left]] < t_count[s[left]]: + match_num -= 1 + left += 1 + min_window_left, min_window_right = min_window_index + if min_window_right == math.inf: + return "" + return s[min_window_left : min_window_right + 1] diff --git a/grind75_hard/01_76_Minimum Window Substring/level_3.py b/grind75_hard/01_76_Minimum Window Substring/level_3.py new file mode 100644 index 0000000..2bf6ada --- /dev/null +++ b/grind75_hard/01_76_Minimum Window Substring/level_3.py @@ -0,0 +1,27 @@ +class Solution: + def minWindow(self, s: str, t: str) -> str: + t_count = defaultdict(int) + for c in t: + t_count[c] += 1 + left = 0 + min_window_index = (left, math.inf) + window_count = defaultdict(int) + match_num = 0 + for right, c in enumerate(s): + if c not in t_count: + continue + window_count[c] += 1 + if window_count[c] == t_count[c]: + match_num += 1 + while left <= right and match_num == len(t_count): + if right - left + 1 < min_window_index[1] - min_window_index[0] + 1: + min_window_index = (left, right) + if s[left] in t_count: + window_count[s[left]] -= 1 + if window_count[s[left]] < t_count[s[left]]: + match_num -= 1 + left += 1 + left, right = min_window_index + if right == math.inf: + return "" + return s[left : right + 1] diff --git a/grind75_hard/01_76_Minimum Window Substring/level_4.py b/grind75_hard/01_76_Minimum Window Substring/level_4.py new file mode 100644 index 0000000..b4ec868 --- /dev/null +++ b/grind75_hard/01_76_Minimum Window Substring/level_4.py @@ -0,0 +1,28 @@ +# 変数名の修正 +# defaultdectを[0]*128に変更 +# tに含まれていない文字もカウントするように修正 +class Solution: + def minWindow(self, s: str, t: str) -> str: + num_chars_in_t = [0] * 128 + for c in t: + num_chars_in_t[ord(c)] += 1 + num_needed_matches = 128 - num_chars_in_t.count(0) + left = 0 + num_matches = 0 + num_chars_in_window = [0] * 128 + min_window_index = (left, len(s)) + for right, c in enumerate(s): + num_chars_in_window[ord(c)] += 1 + if num_chars_in_window[ord(c)] == num_chars_in_t[ord(c)]: + num_matches += 1 + while left <= right and num_matches == num_needed_matches: + if right - left + 1 < min_window_index[1] - min_window_index[0] + 1: + min_window_index = (left, right) + num_chars_in_window[ord(s[left])] -= 1 + if num_chars_in_window[ord(s[left])] < num_chars_in_t[ord(s[left])]: + num_matches -= 1 + left += 1 + min_window_left, min_window_right = min_window_index + if min_window_right == len(s): + return "" + return s[min_window_left : min_window_right + 1]