From 4cc7b6cfe053b8aaafb3c64dae1845ad124d08d2 Mon Sep 17 00:00:00 2001 From: mayota Date: Thu, 11 Jun 2026 21:14:25 +0900 Subject: [PATCH 1/3] step1 --- 703-Kth-Largest-Element-in-a-Stream/note.md | 12 ++++++ 703-Kth-Largest-Element-in-a-Stream/step1.py | 24 +++++++++++ .../step1_heap.py | 41 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 703-Kth-Largest-Element-in-a-Stream/note.md create mode 100644 703-Kth-Largest-Element-in-a-Stream/step1.py create mode 100644 703-Kth-Largest-Element-in-a-Stream/step1_heap.py diff --git a/703-Kth-Largest-Element-in-a-Stream/note.md b/703-Kth-Largest-Element-in-a-Stream/note.md new file mode 100644 index 0000000..602385e --- /dev/null +++ b/703-Kth-Largest-Element-in-a-Stream/note.md @@ -0,0 +1,12 @@ +# 703. Kth Largest Element in a Stream + + + +## step1(まず通す) + +ヒープを書くのに自信がなかったので、最初にソートしてあとは2分探索で挿入してくコードを書いた。 +ヒープは書こうとしてとしてめっちゃ時間をかけてしまった。混乱しながら書いているのでとても効率の悪いコードになっている。時間がもったいないのでもっと早く他の人のコードを読みにいくべきだった。 + +## step2(整形&他の人のコードを読む) + +## step3(10分以内にさっとかける * 3回) diff --git a/703-Kth-Largest-Element-in-a-Stream/step1.py b/703-Kth-Largest-Element-in-a-Stream/step1.py new file mode 100644 index 0000000..90635b2 --- /dev/null +++ b/703-Kth-Largest-Element-in-a-Stream/step1.py @@ -0,0 +1,24 @@ +from typing import List + + +class KthLargest: + def __init__(self, k: int, nums: List[int]): + self.k = k + self.descending_nums = sorted(nums, reverse=True) + + def add(self, val: int) -> int: + expanded_nums = [float("inf")] + self.descending_nums + [float("-inf")] + interval_head = 0 + interval_tail = len(expanded_nums) - 1 + interval_center = (interval_tail + interval_head) // 2 + while interval_head != interval_tail: + if val >= expanded_nums[interval_center]: + interval_tail = interval_center + interval_center = (interval_tail + interval_head) // 2 + else: + interval_head = interval_center + 1 + interval_center = (interval_tail + interval_head) // 2 + + self.descending_nums.insert(interval_head - 1, val) + + return self.descending_nums[self.k - 1] diff --git a/703-Kth-Largest-Element-in-a-Stream/step1_heap.py b/703-Kth-Largest-Element-in-a-Stream/step1_heap.py new file mode 100644 index 0000000..9d4ab83 --- /dev/null +++ b/703-Kth-Largest-Element-in-a-Stream/step1_heap.py @@ -0,0 +1,41 @@ +from typing import List + + +class KthLargest: + def __init__(self, k: int, nums: List[int]): + self.k = k + self.max_heap_nums = self.max_heapify(nums) + + def max_heapify_root(self, nums: List[int], parent: int, tail: int): + while True: + left_child = parent * 2 + 1 + right_child = (parent + 1) * 2 + largest = parent + if left_child <= tail and nums[largest] < nums[left_child]: + largest = left_child + if right_child <= tail and nums[largest] < nums[right_child]: + largest = right_child + + if largest != parent: + nums[parent], nums[largest] = nums[largest], nums[parent] + parent = largest + else: + return + + def max_heapify(self, nums: List[int]): + + tail = len(nums) - 1 + for parent in range(len(nums) // 2, -1, -1): + self.max_heapify_root(nums, parent, tail) + + return nums + + def add(self, val: int) -> int: + self.max_heap_nums = [val] + self.max_heap_nums + self.max_heapify_root(self.max_heap_nums, 0, len(self.max_heap_nums) - 1) + rest = self.max_heap_nums + for _ in range(self.k): + rest_largest = rest[0] + rest = self.max_heapify(rest[1:]) + + return rest_largest From 04c1e8b47307d77c1f1a8fce0500671d3bd5d67d Mon Sep 17 00:00:00 2001 From: mayota Date: Thu, 11 Jun 2026 23:16:04 +0900 Subject: [PATCH 2/3] step2 --- 703-Kth-Largest-Element-in-a-Stream/note.md | 23 +++++- 703-Kth-Largest-Element-in-a-Stream/step2.py | 74 ++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 703-Kth-Largest-Element-in-a-Stream/step2.py diff --git a/703-Kth-Largest-Element-in-a-Stream/note.md b/703-Kth-Largest-Element-in-a-Stream/note.md index 602385e..80cc13b 100644 --- a/703-Kth-Largest-Element-in-a-Stream/note.md +++ b/703-Kth-Largest-Element-in-a-Stream/note.md @@ -5,8 +5,29 @@ ## step1(まず通す) ヒープを書くのに自信がなかったので、最初にソートしてあとは2分探索で挿入してくコードを書いた。 -ヒープは書こうとしてとしてめっちゃ時間をかけてしまった。混乱しながら書いているのでとても効率の悪いコードになっている。時間がもったいないのでもっと早く他の人のコードを読みにいくべきだった。 +ヒープは書こうとしてとしてめちゃくちゃ時間をかけてしまった。非常に混乱しながら書いているのでとても効率の悪いコードになっている。時間がもったいないのでもっと早く他の人のコードを読みにいくべきだった。 ## step2(整形&他の人のコードを読む) +- そもそも insert している時点で挿入部分の時間計算量が配列の長さnに対して O(n) あるので2分探索じゃなくていっそ線形に探索した方が楽だった +- heapq というライブラリがあるのでそれを使えば話が早そうではある + - +- みなさん、max ヒープを作って k 回 pop するんじゃなくて、k 要素の min ヒープを作っていらっしゃる + - など + - 「k番目に大きい=大きい方からk要素だけの中で最小」なので、こうすると判定が早い +- 簡単にセルフ実装してみた。最初 push を↓のように書いていて時間計算量がO(配列長さ) だなあと思っていたところ CPython では 末尾を pop してから先頭をその値で上書きしていた。なるほどいいやり方だ。 + - +- 親の位置をビット演算で計算しているのも勉強になる + - +- 最初書いた時はクラスのメンバ変数として Minheap.heap を持たせたために self.heap を直接いじるメソッドと引数として受け取るメソッドが混在していたので改善した + - CPython の heapq は関数を集めた名前空間 + +```python + def pop(self) -> int: + head = self.heap[0] + # 配列をスライスしているので O(k) かかるがそれで良いのかと思ったが + self.heap = self.heapify(self.heap[1:]) + return head +``` + ## step3(10分以内にさっとかける * 3回) diff --git a/703-Kth-Largest-Element-in-a-Stream/step2.py b/703-Kth-Largest-Element-in-a-Stream/step2.py new file mode 100644 index 0000000..e15009d --- /dev/null +++ b/703-Kth-Largest-Element-in-a-Stream/step2.py @@ -0,0 +1,74 @@ +from typing import List + + +class KthLargest: + def __init__(self, k: int, nums: List[int]): + self.k = k + self.k_largest_elements = self.heapify(nums) + + def add(self, val: int) -> int: + self.push(self.k_largest_elements, val) + return self.k_largest_elements[0] + + def _parent(self, child: int) -> int: + return (child - 1) // 2 + + def _left_child(self, parent: int) -> int: + return parent * 2 + 1 + + def _right_child(self, parent: int) -> int: + return (parent + 1) * 2 + + def _shift_up(self, heap: List[int], index: int): + while index > 0 and heap[index] < heap[self._parent(index)]: + heap[index], heap[self._parent(index)] = ( + heap[self._parent(index)], + heap[index], + ) + index = self._parent(index) + + def _shift_down(self, heap: List[int], index: int): + heap_size = len(heap) + while True: + smallest = index + if ( + self._left_child(index) < heap_size + and heap[self._left_child(index)] < heap[smallest] + ): + smallest = self._left_child(index) + if ( + self._right_child(index) < heap_size + and heap[self._right_child(index)] < heap[smallest] + ): + smallest = self._right_child(index) + + if smallest == index: + break + heap[index], heap[smallest] = ( + heap[smallest], + heap[index], + ) + index = smallest + + def push(self, heap: List[int], num: int): + heap_size = len(heap) + if heap_size < self.k: + heap.append(num) + self._shift_up(heap, len(heap) - 1) + elif num > heap[0]: + heap[0] = num + self._shift_down(heap, 0) + + def pop(self, heap: List[int]) -> int: + head = heap[0] + tail = heap.pop() + if heap: + heap[0] = tail + self._shift_down(heap, 0) + return head + + def heapify(self, nums: List[int]) -> List[int]: + heap: List[int] = [] + for index in range(len(nums)): + self.push(heap, nums[index]) + return heap From e8537748ec6c36b61a17a24a95c015948986b8d1 Mon Sep 17 00:00:00 2001 From: mayota Date: Thu, 11 Jun 2026 23:34:00 +0900 Subject: [PATCH 3/3] step3 --- 703-Kth-Largest-Element-in-a-Stream/step3.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 703-Kth-Largest-Element-in-a-Stream/step3.py diff --git a/703-Kth-Largest-Element-in-a-Stream/step3.py b/703-Kth-Largest-Element-in-a-Stream/step3.py new file mode 100644 index 0000000..f8539e1 --- /dev/null +++ b/703-Kth-Largest-Element-in-a-Stream/step3.py @@ -0,0 +1,17 @@ +from typing import List +import heapq + + +class KthLargest: + def __init__(self, k: int, nums: List[int]): + self.k = k + self.k_largest_elements = [] + for num in nums: + self.add(num) + + def add(self, val: int) -> int: + if len(self.k_largest_elements) < self.k: + heapq.heappush(self.k_largest_elements, val) + elif val > self.k_largest_elements[0]: + heapq.heappushpop(self.k_largest_elements, val) + return self.k_largest_elements[0]