-
Notifications
You must be signed in to change notification settings - Fork 0
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,136 @@ | ||
# Kth Largest Element in a Stream | ||
|
||
## step1 | ||
- 手でやる場合を考える | ||
- リストを用意する | ||
- 新しいものをリストに入れて大きい順に並び替える | ||
- K番目を取り出す | ||
- 下のコードを書いた | ||
- 10分くらい | ||
```python | ||
class KthLargest: | ||
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.k = k | ||
self.nums = nums | ||
|
||
def add(self, val: int) -> int: | ||
self.nums.append(val) | ||
self.nums.sort(reverse = True) | ||
return self.nums[self.k - 1] | ||
``` | ||
|
||
## step2 他の人のコードを見る・自分の改善 | ||
|
||
### 読んだコード | ||
|
||
https://github.com/tarinaihitori/leetcode/pull/8/files/b93a4ee64137e37666b03b99b6c0602ce8cf2a10#diff-6e7e84a8c0c13aabe8bad58b32c7215762116a974e2143b20ee931bf24b51a2f | ||
https://github.com/katataku/leetcode/pull/8/files/7c8c51d9b82aa240bd4a4b5ed8bb657ba137baf5#diff-6e7e84a8c0c13aabe8bad58b32c7215762116a974e2143b20ee931bf24b51a2f | ||
https://github.com/haniwachann/leetcode/pull/1/files/991655bbb5a07f7c508494233b6b22494d5517df#diff-6f3d970863dc500b1778101efd01e2a76334accabb99be3850492a4e4c30240d | ||
|
||
- この方はC++でやってる。いずれは自分もpython以外を読めるようになった方がいい気がしている | ||
- 割と読めた。C++とpythonは似てるから割と読めるんですね | ||
|
||
|
||
- [heapというものがあるらしい](https://github.com/tarinaihitori/leetcode/pull/8/files/b93a4ee64137e37666b03b99b6c0602ce8cf2a10#diff-6e7e84a8c0c13aabe8bad58b32c7215762116a974e2143b20ee931bf24b51a2f) | ||
- heap queとは | ||
- [heapqのドキュメント](https://docs.python.org/3/library/heapq.html) | ||
- 全ての親ノードの値が子ノードの値以下であるバイナリツリー | ||
- log(n)で追加や削除が行えるので速い | ||
- k番目の要素のみを取得できればいいので他の要素が大きい順に並んでいる必要などはない | ||
heapqを使った実装<https://github.com/katataku/leetcode/pull/8/files/7c8c51d9b82aa240bd4a4b5ed8bb657ba137baf5#diff-6e7e84a8c0c13aabe8bad58b32c7215762116a974e2143b20ee931bf24b51a2f> | ||
|
||
- initでheapqを作成するときも個別の操作を書くのではなくaddを使用することでコードがシンプルになっているのが良いと感じた | ||
```python | ||
class KthLagest: | ||
|
||
def __init__(self, k: int, nums: List[int]): | ||
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. タブでインデントをするのは、最近ではあまり見かけないように思います。スペースでインデントすることをお勧めいたします。 https://peps.python.org/pep-0008/#tabs-or-spaces
https://google.github.io/styleguide/pyguide.html#s3.4-indentation
|
||
self.k = k | ||
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. k が 0 だと add で困りそうです。
などいくつか対応があり状況次第です。何が好ましいか自問自答する癖をつけて想像しておきましょう。 |
||
self.kth_largest_nums = [] | ||
for num in nums: | ||
self.add(num) | ||
|
||
def add(self, val: int) -> int: | ||
heapq.heappush(self.kth_largest_nums, val) | ||
if len(self._kth_largest_nums) > self.k: | ||
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.
個人的には while の方が意図がはっきりする気はします。if だと、これが 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. 結果的に一つ削除すれば十分なだけで、やりたいこととしては要素がk個になるまで削除するということなので確かにwhileの方が適切であるように思いました。 |
||
heapq.heappop(self.kth_largest_nums) | ||
return self.kth_largest_nums[0] | ||
|
||
``` | ||
|
||
heapifyを使う実装も考えられる | ||
|
||
```python | ||
class KthLargest: | ||
|
||
def __init_(self, k: int, nums: List[int]) | ||
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. nit: |
||
self.k = k | ||
self.nums = nums | ||
|
||
heapq.heapify(self.nums) | ||
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. 入力として与えられている nums の中身を変更している点が気になりました。このクラスを呼び出す側の立場に立って考えてみると、与えた nums の中身が変更されるのは、意図しない動作に感じられるのではないかと思います。そのような場合は、 nums のコピーを保持し、そちらを変更するようにするか、コメントで nums の中身を変更することを明示したほうが良いと思います。 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. その視点はなかったです。ありがとうございます。 |
||
|
||
while k < len(self.nums): | ||
heapq.heappop(self.nums) | ||
|
||
def add(self, val: int) -> int: | ||
heapq.heappush(self.nums, val) | ||
|
||
if len(self.nums) > self.k: | ||
heapq.heappop(self.nums) | ||
return self.nums[0] | ||
``` | ||
|
||
[C++であればmultisetが使える](https://github.com/haniwachann/leetcode/pull/1/files/991655bbb5a07f7c508494233b6b22494d5517df#diff-6f3d970863dc500b1778101efd01e2a76334accabb99be3850492a4e4c30240d) | ||
- pythonに同じようなライブラリーはないのだろうか | ||
- 外部ライブラリーに[SortedList](https://grantjenks.com/docs/sortedcontainers/sortedlist.html)がある | ||
Comment on lines
+83
to
+85
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. 見た感じ内部実装はちょっと違いそうですね 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. 自動でソートされるという機能のみに注目しており、内部実装まではきちんと比較しておりませんでした。コメントありがとうございます。 |
||
- log(n)で挿入、削除が可能 | ||
- [SortedListの仕組み](https://zenn.dev/pokeshun/articles/f5362825e512cf) | ||
- Listの要素を分割して保持している | ||
- Listの分割サイズが1000であるためkが小さい問題では普通のListとあまり変わらないのではないか | ||
SortedListの場合 | ||
|
||
```python | ||
from sortedcontainer import SortedList | ||
|
||
|
||
class KthLargest: | ||
|
||
def __init__(self,k: int,nums: List[int]): | ||
self.k = k | ||
self.nums = SortedList() | ||
|
||
for num in nums: | ||
self.add(num) | ||
|
||
def add(self, val: int) -> int: | ||
self.nums.add(val) | ||
|
||
if len(self.nums) > self.k: | ||
self.nums.pop(0) | ||
|
||
return self.nums[0] | ||
``` | ||
|
||
## Step3 | ||
|
||
heapqを使った実装を書いてみる | ||
```python | ||
class KthLargest: | ||
def __init__(self, k: int, nums: List[int]): | ||
self.k = k | ||
self.kth_largest = [] | ||
|
||
for num in nums: | ||
self.add(num) | ||
|
||
def add(self, val: int): | ||
heapq.heappush(self.kth_largest, val) | ||
|
||
if len(self.kth_largest) > self.k: | ||
heapq.heappop(self.kth_largest) | ||
|
||
return self.kth_largest[0] | ||
|
||
``` | ||
|
||
タイピングのミスがめっちゃ多い。タイピングを鍛えるにはたくさん書くしかないのだろうか。 | ||
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. まあ実際にはエディタ側の補完などもあるので、そこまで気にしなくても良いかもしれないです。 |
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.
nits:些細ですが。
https://docs.python.org/3/library/heapq.html