-
Notifications
You must be signed in to change notification settings - Fork 0
703. Kth Largest Element in a Stream #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| ## 考察 | ||
| - 過去に解いたことあり | ||
| - 常にk番目に大きい要素を高速に取り出せる状態にしておきたい | ||
| - 各クエリでkが固定なところもポイントだと思う | ||
| - 方針は4つ思い浮かぶ | ||
| - ソート済みnumsを保つ | ||
| - 二分探索で挿入ポイントを探して、insertする(insertにO(n)かかる) | ||
| - 初期化: O(n log n), 各クエリ: O(n) | ||
| - 最小ヒープを使う | ||
| - ヒープのサイズをkに保つ | ||
| - 初期化: O(n log k), 各クエリ: O(log k) | ||
| - fenwick tree上の二分探索(もしくはsegment tree上の二分探索) | ||
| - -10^4 <= nums[i] <= 10^4 かつ -10^4 <= val <= 10^4 なので、種類としては高々2 * 10^4 + 1 | ||
| - 各数字が何回現れたかを管理できる | ||
| - kが各クエリで変わるときは、この方法になると思う(今回はk固定なのでスキップ) | ||
| - 初期化: O(n log n), 各クエリ: O(log n) | ||
| - 平衡二分探索木 | ||
| - たぶん最終手段だと思う | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Python で使いたかったら、標準でないライブラリーがあります。C++ では標準で平衡木がありますね。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. こちら調べてみました。
実装を追加してます。-> f382024 |
||
| - Pythonにはライブラリはない、一から実装することになりそう(かなり大変そうなイメージ、実装したことはない) | ||
| - 最も効率の良い最小ヒープでやる | ||
| - あとは実装 | ||
|
|
||
| ## Step1 | ||
| - 最小ヒープで実装 | ||
| - time: O(n log k), space: O(k) | ||
|
|
||
| ## Step2 | ||
| - 他の人のPRを検索してみた | ||
| - Pythonにはheappushpopというのがあるらしい | ||
| - Ref. https://github.com/kagetora0924/leetcode-grind/pull/9#discussion_r1633996701 | ||
| - heappush()とheappop()を個別に呼び出すよりも効率が良い | ||
| - `Push item on the heap, then pop and return the smallest item from the heap. The combined action runs more efficiently than heappush() followed by a separate call to heappop().` | ||
| - Ref. https://docs.python.org/3/library/heapq.html#heapq.heappushpop | ||
| - heappushpopを使ってみた | ||
|
|
||
| ## Step3 | ||
| - 1回目: 1m46s | ||
| - 2回目: 1m51s | ||
| - 3回目: 1m42s | ||
|
|
||
| ## Step4 | ||
| - レビューを元に修正 | ||
| - `__init__` 内で、`add` を流用できたためシンプルになった | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| class KthLargest: | ||
| def __init__(self, k: int, nums: List[int]): | ||
| self.k = k | ||
| self.num_min_heap = [] | ||
| for num in nums: | ||
| heapq.heappush(self.num_min_heap, num) | ||
| if len(self.num_min_heap) > self.k: | ||
| heapq.heappop(self.num_min_heap) | ||
|
|
||
| def add(self, val: int) -> int: | ||
| heapq.heappush(self.num_min_heap, val) | ||
| if len(self.num_min_heap) > self.k: | ||
| heapq.heappop(self.num_min_heap) | ||
| return self.num_min_heap[0] | ||
|
|
||
|
|
||
|
|
||
| # Your KthLargest object will be instantiated and called as such: | ||
| # obj = KthLargest(k, nums) | ||
| # param_1 = obj.add(val) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| from sortedcontainers import SortedList | ||
|
|
||
| class KthLargest: | ||
| def __init__(self, k: int, nums: List[int]): | ||
| self.k = k | ||
| self.tree = SortedList(nums) | ||
|
|
||
| def add(self, val: int) -> int: | ||
| self.tree.add(val) | ||
| return self.tree[len(self.tree) - self.k] | ||
|
|
||
|
|
||
|
|
||
| # Your KthLargest object will be instantiated and called as such: | ||
| # obj = KthLargest(k, nums) | ||
| # param_1 = obj.add(val) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| #include <ext/pb_ds/assoc_container.hpp> | ||
| #include <ext/pb_ds/tree_policy.hpp> | ||
|
|
||
| using namespace __gnu_pbds; | ||
| template <typename T> | ||
| using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>; | ||
|
|
||
| class KthLargest { | ||
| private: | ||
| int k; | ||
| ordered_multiset<int> binary_search_tree; | ||
|
|
||
| public: | ||
| KthLargest(int k, vector<int>& nums) : k(k) { | ||
| for (int num : nums) { | ||
| binary_search_tree.insert(num); | ||
| } | ||
| } | ||
|
|
||
| int add(int val) { | ||
| binary_search_tree.insert(val); | ||
| auto it = binary_search_tree.find_by_order(binary_search_tree.size() - k); | ||
| return *it; | ||
| } | ||
| }; | ||
|
|
||
| /** | ||
| * Your KthLargest object will be instantiated and called as such: | ||
| * KthLargest* obj = new KthLargest(k, nums); | ||
| * int param_1 = obj->add(val); | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| class KthLargest: | ||
| def __init__(self, k: int, nums: List[int]): | ||
| self.k = k | ||
| self.num_min_heap = [] | ||
| for num in nums: | ||
| if len(self.num_min_heap) < self.k: | ||
| heapq.heappush(self.num_min_heap, num) | ||
| else: | ||
| heapq.heappushpop(self.num_min_heap, num) | ||
|
|
||
| def add(self, val: int) -> int: | ||
| if len(self.num_min_heap) < self.k: | ||
| heapq.heappush(self.num_min_heap, val) | ||
| else: | ||
| heapq.heappushpop(self.num_min_heap, val) | ||
| return self.num_min_heap[0] | ||
|
|
||
|
|
||
|
|
||
| # Your KthLargest object will be instantiated and called as such: | ||
| # obj = KthLargest(k, nums) | ||
| # param_1 = obj.add(val) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| class KthLargest: | ||
| def __init__(self, k: int, nums: List[int]): | ||
| self.k = k | ||
| self.num_min_heap = [] | ||
| for num in nums: | ||
| if len(self.num_min_heap) < k: | ||
| heapq.heappush(self.num_min_heap, num) | ||
| else: | ||
| heapq.heappushpop(self.num_min_heap, num) | ||
|
Comment on lines
+5
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. こちら、 for num in nums:
self.add(num)
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 気付きませんでした。シンプルになりますね。 |
||
|
|
||
| def add(self, val: int) -> int: | ||
| if len(self.num_min_heap) < self.k: | ||
| heapq.heappush(self.num_min_heap, val) | ||
| else: | ||
| heapq.heappushpop(self.num_min_heap, val) | ||
| return self.num_min_heap[0] | ||
|
|
||
|
|
||
|
|
||
| # Your KthLargest object will be instantiated and called as such: | ||
| # obj = KthLargest(k, nums) | ||
| # param_1 = obj.add(val) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| class KthLargest: | ||
| def __init__(self, k: int, nums: List[int]): | ||
| self.k = k | ||
| self.num_min_heap = [] | ||
| for num in nums: | ||
| self.add(num) | ||
|
|
||
| def add(self, val: int) -> int: | ||
| if len(self.num_min_heap) < self.k: | ||
| heapq.heappush(self.num_min_heap, val) | ||
| else: | ||
| heapq.heappushpop(self.num_min_heap, val) | ||
| return self.num_min_heap[0] | ||
|
|
||
|
|
||
|
|
||
| # Your KthLargest object will be instantiated and called as such: | ||
| # obj = KthLargest(k, nums) | ||
| # param_1 = obj.add(val) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(コードへのコメントではないですが。) fenwick tree 知らなかったので勉強になりました!