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
40 changes: 40 additions & 0 deletions grind75_hard/08_23_Merge k Sorted Lists/level_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 要素を全て入れて、sortしてからlinked listに変換
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
lists_val = []
for node in lists:
while node:
lists_val.append(node.val)
node = node.next
lists_val.sort()
sentinel = ListNode()
node = sentinel
for i in lists_val:
node.next = ListNode(i)
node = node.next

return sentinel.next


# 各linked listの先頭を比較していく
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
sentinel = ListNode()
node = sentinel
while lists:
min_val = float("inf")
for i in range(len(lists)):
if not lists[i] or lists[i].val > min_val:
continue
min_val = lists[i].val
min_index = i
if min_val == float("inf"):
break
node.next = ListNode(min_val)
node = node.next
min_node = lists.pop(min_index)
min_node = min_node.next
if min_node:
lists.append(min_node)

return sentinel.next
19 changes: 19 additions & 0 deletions grind75_hard/08_23_Merge k Sorted Lists/level_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# heapqに先頭の値だけを入れていく
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
min_heap = []
for i, node in enumerate(lists):
if not node:
continue
heapq.heappush(min_heap, (node.val, i, node))
sentinel = ListNode()
node = sentinel
while min_heap:
val, index, smallest_head = heapq.heappop(min_heap)
node.next = ListNode(val)
node = node.next
if smallest_head.next:
heapq.heappush(
min_heap, (smallest_head.next.val, index, smallest_head.next)
)
return sentinel.next
18 changes: 18 additions & 0 deletions grind75_hard/08_23_Merge k Sorted Lists/level_3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
min_heap = []
for i, node in enumerate(lists):
if not node:
continue
heapq.heappush(min_heap, (node.val, i, node))
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

Choose a reason for hiding this comment

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

これがないと、定義されていないListNodeの比較になって問題が出るのですかね。

Copy link
Copy Markdown
Owner Author

@shining-ai shining-ai May 24, 2024

Choose a reason for hiding this comment

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

問題文上は不要です。

これがないと、定義されていないListNodeの比較になって問題が出るのですかね。

おっしゃる通りで、同値の比較のために入れていました。
この旨はコメントで書いておかないと、疑問を持たれてしまいますね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

同じ値があったときに、オブジェクトの < が定義されていないからエラーということですね。

sentinel = ListNode()
node = sentinel
while min_heap:
val, index, smallest_head = heapq.heappop(min_heap)
node.next = ListNode(val)
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.

こういうことですかね。

val, index, smallest_head = heapq.heappop(min_heap)
node.next = smallest_head
node = node.next

既存のノードのnextは必ず上書きされるので、新しく作った方が分かりやすいかなと考えてました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

in-placeなのか新しく作るのかは、要件によるかと思います。

node = node.next
if smallest_head.next:
heapq.heappush(
min_heap, (smallest_head.next.val, index, smallest_head.next)
)
return sentinel.next
52 changes: 52 additions & 0 deletions grind75_hard/08_23_Merge k Sorted Lists/level_4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
min_heap = []
for i, node in enumerate(lists):
if not node:
continue
# node.valが同値の場合にListNodeで比較しないようにindexをheapに追加
heapq.heappush(min_heap, (node.val, i, node))
sentinel = ListNode()
node = sentinel
while min_heap:
val, index, smallest_head = heapq.heappop(min_heap)
node.next = smallest_head
node = node.next
if smallest_head.next:
heapq.heappush(
min_heap, (smallest_head.next.val, index, smallest_head.next)
)
return sentinel.next


# マージソートをイメージした解法
# 先頭の2つのリストをマージしていき、最後の1つになるまで繰り返す
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
def merge_two_lists(list_1, list_2):
sentinel = ListNode()
node = sentinel
while list_1 and list_2:
if list_1.val < list_2.val:
node.next = list_1
list_1 = list_1.next
else:
node.next = list_2
list_2 = list_2.next
node = node.next
if not list_1:
node.next = list_2
else:
node.next = list_1
return sentinel.next

list_queue = deque(lists)
if not list_queue:
return None
while 1:
list_1 = list_queue.popleft()
if not list_queue:
return list_1
list_2 = list_queue.popleft()
mearged_list = merge_two_lists(list_1, list_2)
list_queue.append(mearged_list)