-
Notifications
You must be signed in to change notification settings - Fork 0
703. Kth Largest Element in a Stream #8
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
Conversation
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.
良いと思います!これはよもやま話ですが、heapqはmin-heapですが、入れる値の正負を逆転させてmax-heapにすることもできることを、私自身どこかで聞かれたような記憶があります。
heap_nums: List[int] | ||
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.heap_nums = heapq.nlargest(k, nums) |
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.
nums
も
the stream of test scores
とあり、streamなので、stream processingとかを思い出すと、for文でひとつずつ処理していくことが想定解ではないでしょうか?
問題文が悪いですし、軽く調べてもよく分からず私も自信がないのですが... 😥
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.
後のコメントでも触れていただいているのですが、nlargest+sortの方法だと読み手に考えさせてしまうのでより素直にfor文でnumsを回しながらaddする方法を選択しました!
4c0fb63
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.heap_nums = heapq.nlargest(k, nums) | ||
self.heap_nums.sort() |
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.
sorted listって、array実装のmin-heapなんですね 👀 heapがarrayでどう実装されているのか分からない読者にはheapify()
の方が、heapである、という抽象度で止まって深掘りする必要がなくなるので親切かもしれません。これくらいは一般常識なのかもしれませんが 🤔
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.
私は一瞬これheapになっているのか?と考えて問題ないことを確認しました。huyfififiさんと同じ意見です。
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.
たしかにその通りですね。
nlargest + sortの方法だとヒープの実装までイメージする必要があって読み手に負荷をかけてしまいます
素直にfor文でnumsの要素を走査しながらaddする実装にしました
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.
シンプルで理解しやすくて良いと思います 👍
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.k = k | ||
self.top_k_min_heap = sorted(heapq.nlargest(k, nums)) |
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.
私もtop_k_min_heap
派ですが、クラス名とk
というinstance attributeに既に情報があるので、単にmin_heap
にしてしまう方もいるだろうな、と予想します。
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.
「こういう人もいるだろう」コメント勉強になります
クラス名やkというコンテキストがあるので min_heap でも充分通じそうですね
これは好みになるんですが、min_heapだけ見たときに一瞬考えるかもなと思い top_k_min_heap が良いかなと思いました
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.k = k | ||
self.top_k_min_heap = sorted(heapq.nlargest(k, nums)) |
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.
self.top_k_min_heap = heapq.nlargest(k, nums)[::-1] でも可でしょうか。
- top_k_min_heap | ||
とかかな? | ||
データ構造を示さなくてよいなら、top_k_valsとかもありそう。 | ||
今回はヒープであることを明示したいので、top_k_min_heapがよさそう。 |
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.
PythonではheapはただのListを介して操作されるのでわかりにくい印象で、変数名に書く方法はわかりやすいと思いました。
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.
@huyfififi @tokuhirat
レビューありがとうございます!
コメント返信しました
heap_nums: List[int] | ||
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.heap_nums = heapq.nlargest(k, nums) |
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.
後のコメントでも触れていただいているのですが、nlargest+sortの方法だと読み手に考えさせてしまうのでより素直にfor文でnumsを回しながらaddする方法を選択しました!
4c0fb63
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.heap_nums = heapq.nlargest(k, nums) | ||
self.heap_nums.sort() |
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.
たしかにその通りですね。
nlargest + sortの方法だとヒープの実装までイメージする必要があって読み手に負荷をかけてしまいます
素直にfor文でnumsの要素を走査しながらaddする実装にしました
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.k = k | ||
self.top_k_min_heap = sorted(heapq.nlargest(k, nums)) |
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.
「こういう人もいるだろう」コメント勉強になります
クラス名やkというコンテキストがあるので min_heap でも充分通じそうですね
これは好みになるんですが、min_heapだけ見たときに一瞬考えるかもなと思い top_k_min_heap が良いかなと思いました
|
||
```python | ||
import heapq | ||
class KthLargest: |
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.
nit
Surround top-level function and class definitions with two blank lines.
とあり、import文とその他ロジックは2つのblank linesで分けていただいた方が無難かと思います。
self.heap_nums = heapq.nlargest(k, nums) | ||
self.heap_nums.sort() |
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.
nlargest + sort でもいいんですが、nlargest の中身を読むと、全部 heap にいれて k 個取り出すとかだったと思います。そう考えると何か二度手間をしている感じがします。小さい方から k 個取り出すだけならば、アルゴリズムとしては、quickselect があるんですが (C++ だと nth_element) Python だとなさそうですね。
なんとなく被っているのと、sort で heap を作っているのが驚きを与えそうですね。sort よりも heapq.heapify を使ったほうが素直でしょう。
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.
- n要素取ってきてheapify
- 残りの要素をheapreplace
- ソート
という処理になっていました
なのでnlargest + sortは2回ソートしているので2度手間になっていますね
quickselectを確認し、実装してみました
c53131e
https://github.com/shintaro1993/arai60/pull/12/files | ||
2分探索で解く方法もある。 | ||
addにO(logn)(nはnumsの要素数)かかる。k<=n+1なのでヒープを使った解法のほうが早そう。 | ||
と思ったけど、最初にソートしてk番目までの最大値をソートされたまま保持しておけばO(logk)でaddできるか |
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.
こういうソートされた状態での追加削除は、平衡二分木の出番なんですが、Python だと標準にはなくて、標準ではないけれども SortedContainers などを使うことが多いです。
https://grantjenks.com/docs/sortedcontainers/
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.
なるほど、実装してみました。
1117820
問題:703. Kth Largest Element in a Stream
次の問題:347. Top K Frequent Elements