diff --git a/0539.Minimum-Time-Difference/memo.md b/0539.Minimum-Time-Difference/memo.md new file mode 100644 index 0000000..0bcb6df --- /dev/null +++ b/0539.Minimum-Time-Difference/memo.md @@ -0,0 +1,23 @@ +# 539. Minimum Time Difference + +## step1 +ソートする解法はすぐに思いつく。10m。日をまたぐ差分を考慮せずに一度間違えた。 +計算量O(nlogn) + +## step2 +変数名を改善。 + +https://leetcode.com/problems/minimum-time-difference/editorial/?envType=problem-list-v2&envId=7p55wqm + +バケットソート。全く思いつかなかった。ソート対象の値が限られているときにバケットソートが使えることを覚えておきたい。 +計算量 O(1) + +## step3 + +sortedcontainers.SortedList: 検索、追加、削除が 平均O(logN)で可能なデータ構造(最悪はO(N)) + +一定サイズに分割した二重配列_lists、部分配列の最大値を格納した_maxes、要素数を木構造で管理する_index で管理している + +https://grantjenks.com/docs/sortedcontainers/introduction.html + +https://github.com/grantjenks/python-sortedcontainers/tree/master/src/sortedcontainers diff --git a/0539.Minimum-Time-Difference/step1_sort.py b/0539.Minimum-Time-Difference/step1_sort.py new file mode 100644 index 0000000..d71f410 --- /dev/null +++ b/0539.Minimum-Time-Difference/step1_sort.py @@ -0,0 +1,17 @@ +class Solution: + def findMinDifference(self, timePoints: List[str]) -> int: + def time_to_minutes(time_point: str): + hours, minutes = time_point.split(":") + return 60 * int(hours) + int(minutes) + + minutes = [time_to_minutes(time_point) for time_point in timePoints] + minutes.sort() + minutes.append(minutes[0] + 24 * 60) + + min_difference = float("inf") + for i in range(len(minutes) - 1): + min_difference = min(min_difference, minutes[i+1] - minutes[i]) + + return min_difference + + diff --git a/0539.Minimum-Time-Difference/step2_backet_sort.py b/0539.Minimum-Time-Difference/step2_backet_sort.py new file mode 100644 index 0000000..8a889e1 --- /dev/null +++ b/0539.Minimum-Time-Difference/step2_backet_sort.py @@ -0,0 +1,38 @@ +class Solution: + def findMinDifference(self, timePoints: List[str]) -> int: + MINUTES_IN_DAY = 24 * 60 + + if len(timePoints) > MINUTES_IN_DAY: + return 0 + + def time_to_minutes(time_point: str) -> int: + hours, minutes = time_point.split(":") + return int(hours) * 60 + int(minutes) + + seen = [False] * MINUTES_IN_DAY + for time_point in timePoints: + time_in_minutes = time_to_minutes(time_point) + if seen[time_in_minutes]: + return 0 + seen[time_in_minutes] = True + + min_difference = float("inf") + previous_time = None + first_time = None + last_time = None + for time_in_minutes in range(len(seen)): + if not seen[time_in_minutes]: + continue + + if first_time is None: + first_time = time_in_minutes + previous_time = time_in_minutes + continue + + min_difference = min(min_difference, time_in_minutes - previous_time) + previous_time = time_in_minutes + last_time = time_in_minutes + + min_difference = min(min_difference, first_time - last_time + MINUTES_IN_DAY) + + return min_difference diff --git a/0539.Minimum-Time-Difference/step2_sort.py b/0539.Minimum-Time-Difference/step2_sort.py new file mode 100644 index 0000000..986f2a7 --- /dev/null +++ b/0539.Minimum-Time-Difference/step2_sort.py @@ -0,0 +1,16 @@ +class Solution: + def findMinDifference(self, timePoints: List[str]) -> int: + MINUTES_IN_DAY = 24 * 60 + + def time_to_minutes(time_point: str) -> int: + hours, minutes = time_point.split(":") + return int(hours) * 60 + int(minutes) + + times_in_minutes = sorted(time_to_minutes(time_point) for time_point in timePoints) + times_in_minutes.append(times_in_minutes[0] + MINUTES_IN_DAY) + + min_difference = float("inf") + for i in range(len(times_in_minutes) - 1): + min_difference = min(min_difference, times_in_minutes[i+1] - times_in_minutes[i]) + + return min_difference diff --git a/0539.Minimum-Time-Difference/step3_SortedList.py b/0539.Minimum-Time-Difference/step3_SortedList.py new file mode 100644 index 0000000..01a5d16 --- /dev/null +++ b/0539.Minimum-Time-Difference/step3_SortedList.py @@ -0,0 +1,36 @@ +from sortedcontainers import SortedList + +class Solution: + def findMinDifference(self, timePoints: list[str]) -> int: + MINUTES_IN_DAY = 24 * 60 + + if len(timePoints) > MINUTES_IN_DAY: + return 0 + + def time_to_minutes(time_point: str) -> int: + h, m = time_point.split(":") + return int(h) * 60 + int(m) + + sorted_time_points = SortedList() + min_difference = float("inf") + + for tp in timePoints: + time_in_minutes = time_to_minutes(tp) + if time_in_minutes in sorted_time_points: + return 0 + + index = sorted_time_points.bisect_left(time_in_minutes) + + if index < len(sorted_time_points): + min_difference = min(min_difference, sorted_time_points[index] - time_in_minutes) + elif sorted_time_points: + min_difference = min(min_difference, sorted_time_points[0] + 1440 - time_in_minutes) + + if index > 0: + min_difference = min(min_difference, time_in_minutes - sorted_time_points[index - 1]) + elif sorted_time_points: + min_difference = min(min_difference, time_in_minutes + 1440 - sorted_time_points[-1]) + + sorted_time_points.add(time_in_minutes) + + return min_difference diff --git a/0539.Minimum-Time-Difference/step3_backet_sort.py b/0539.Minimum-Time-Difference/step3_backet_sort.py new file mode 100644 index 0000000..0d52902 --- /dev/null +++ b/0539.Minimum-Time-Difference/step3_backet_sort.py @@ -0,0 +1,36 @@ +class Solution: + def findMinDifference(self, timePoints: List[str]) -> int: + MINUTES_IN_DAY = 24 * 60 + + if len(timePoints) > MINUTES_IN_DAY: + return 0 + + def time_to_minutes(time_point: str) -> int: + h, m = time_point.split(":") + return int(h) * 60 + int(m) + + seen = [False] * MINUTES_IN_DAY + for time_point in timePoints: + time_in_minutes = time_to_minutes(time_point) + if seen[time_in_minutes]: + return 0 + seen[time_in_minutes] = True + + min_difference = float("inf") + previous_time = None + first_time = None + for time_in_minutes in range(len(seen)): + if not seen[time_in_minutes]: + continue + + if first_time is None: + first_time = time_in_minutes + previous_time = time_in_minutes + continue + + min_difference = min(min_difference, time_in_minutes - previous_time) + previous_time = time_in_minutes + + min_difference = min(min_difference, first_time - previous_time + MINUTES_IN_DAY) + + return min_difference