Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions 0539.Minimum-Time-Difference/memo.md
Original file line number Diff line number Diff line change
@@ -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

バケットソート。全く思いつかなかった。ソート対象の値が限られているときにバケットソートが使えることを覚えておきたい。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python だと書きにくいですが、木構造も一つで C++ の lower_bound upper_bound もありかと思いました。
Python なら sortedcontainers ですかね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この管理方法はストリーミング処理に適していそうですね。
sortedcontainers 知らなかったので勉強になりました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

バケットソートも、木構造の分岐が一段で大きさが固定なものという感じなので、そんなに距離はないですね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、バケットソートが一段の木構造という視点はありませんでした。

計算量 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
17 changes: 17 additions & 0 deletions 0539.Minimum-Time-Difference/step1_sort.py
Original file line number Diff line number Diff line change
@@ -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


38 changes: 38 additions & 0 deletions 0539.Minimum-Time-Difference/step2_backet_sort.py
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions 0539.Minimum-Time-Difference/step2_sort.py
Original file line number Diff line number Diff line change
@@ -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
36 changes: 36 additions & 0 deletions 0539.Minimum-Time-Difference/step3_SortedList.py
Original file line number Diff line number Diff line change
@@ -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
36 changes: 36 additions & 0 deletions 0539.Minimum-Time-Difference/step3_backet_sort.py
Original file line number Diff line number Diff line change
@@ -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