-
Notifications
You must be signed in to change notification settings - Fork 0
347. Top K Frequent Elements #10
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,115 @@ | ||||||||||||
# step1 | ||||||||||||
愚直に考えるなら、for文を回してdictに格納し、上からk個取得 | ||||||||||||
頻度(freq)でheapソートをして格納し、そのときにnumもデータに入れる。 | ||||||||||||
その後heappopでk個まで減らしてreturnする。 | ||||||||||||
""" | ||||||||||||
|
||||||||||||
```python | ||||||||||||
class Solution: | ||||||||||||
def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||||||||||||
elements = {} | ||||||||||||
|
||||||||||||
for num in nums: | ||||||||||||
if num in elements: | ||||||||||||
elements[num] += 1 | ||||||||||||
else: | ||||||||||||
elements[num] = 1 | ||||||||||||
|
||||||||||||
elements_order_by_freq = [] | ||||||||||||
for key, value in elements.items(): | ||||||||||||
heapq.heappush(elements_order_by_freq, [value, key]) | ||||||||||||
|
||||||||||||
while len(elements_order_by_freq) > k: | ||||||||||||
heapq.heappop(elements_order_by_freq) | ||||||||||||
|
||||||||||||
most_k_elements = [] | ||||||||||||
for element_order_by_freq in elements_order_by_freq: | ||||||||||||
most_k_elements.append(element_order_by_freq[1]) | ||||||||||||
|
||||||||||||
return most_k_elements | ||||||||||||
``` | ||||||||||||
|
||||||||||||
# step2 | ||||||||||||
参考にした方のPR | ||||||||||||
- https://github.com/t0hsumi/leetcode/pull/9 | ||||||||||||
- https://github.com/katataku/leetcode/pull/9 | ||||||||||||
- https://github.com/tarinaihitori/leetcode/pull/9 | ||||||||||||
- https://github.com/thonda28/leetcode/pull/17 | ||||||||||||
- https://github.com/goto-untrapped/Arai60/pull/55 | ||||||||||||
|
||||||||||||
他の方のPRを見ていたときのメモ | ||||||||||||
- dictを使わなくても、Counterでできる https://docs.python.org/3/library/collections.html#collections.Counter | ||||||||||||
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://docs.python.org/3/library/collections.html#collections.Counter.most_common |
||||||||||||
- [defaultdict](https://docs.python.org/ja/3.6/library/collections.html)とdictの違いがよくわかっていない。defaultdictを使うとstep1の最初のif文が必要なくなる。これは存在しないキーに対しては0が自動的に設定されているから | ||||||||||||
- 前のLeetCodeの問題でも指摘されたこと(厳密にいうと、コードを書いているときにどうやって書くんだっけとなっていた)を忘れていた. | ||||||||||||
``` | ||||||||||||
for num in nums: | ||||||||||||
if num not in elemets: | ||||||||||||
elements[num] = 0 | ||||||||||||
elements[num] += 1 | ||||||||||||
``` | ||||||||||||
- クイックセレクトを使った解法もありましたがこれくらいは"常識"なんですかね? | ||||||||||||
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. Quick Sort は、授業でやるでしょう。Quick select は知っていると思います。 ただ、この問題が出題されたときに選択するかというと少し過剰に大変に思いますね。(そういう考え方も思いついたと口頭で言うくらい。) |
||||||||||||
- 他の方の解答で、returnのところに[num for num, freq in sorted\_num\_to\_freq\_list]みたいにして書いているのは個人的にはあまり好きじゃない(変数に格納してreturn 変数 みたいにしたい)が、これは個人の好みとして片付けて良いのか、"一般的な"ソフトウェアエンジニアが書く方法があるのか気になった。 | ||||||||||||
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. 計算や処理をしているのを変数に格納せずにreturnしているのが個人的に嫌、という理由のほかに、そのような場合は目を移動させて読むことになることが往々にしてあるからというのも感じていました。 ちなみにこちらの方を見ていて質問したいと思ったのですが、PEP8だとlambdaは非推奨とされていると思います。実際にlambdaは使われているんですかね。そもそもlambdaを使ってコードを書くことは少ない(というよりかはpythonにはこんな機能もあります!というような紹介で使っているだけの感じがある)んですが、私が使っていないだけですかね。 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 の考え方に
というのがあります。 これは、Perl の
とは逆です。 lambda は、様々な言語にありますが、他言語と比較したときに「式であるなど、故意にかなり使いにくくしてある」が、あるとありがたいことが稀にあるので用意されている、くらいの温度感で私は見ています。 |
||||||||||||
|
||||||||||||
- step1の改良 | ||||||||||||
```python | ||||||||||||
class Solution: | ||||||||||||
def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||||||||||||
num_to_count = defaultdict(int) | ||||||||||||
for num in nums: | ||||||||||||
num_to_count[num] += 1 | ||||||||||||
|
||||||||||||
sorted_nums = [] | ||||||||||||
for num, freq in num_to_count.items(): | ||||||||||||
heapq.heappush(sorted_nums, (freq, num)) | ||||||||||||
|
||||||||||||
top_k_freq = [] | ||||||||||||
while(len(sorted_nums) > 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と(の間には1つスペースがあるといい様に思いました。 |
||||||||||||
heapq.heappop(sorted_nums) | ||||||||||||
|
||||||||||||
for num in sorted_nums: | ||||||||||||
top_k_freq.append(num[1]) | ||||||||||||
|
||||||||||||
return top_k_freq | ||||||||||||
``` | ||||||||||||
- バケットソート | ||||||||||||
整数のソートにおいて、最大値個のバケツを用意することでメモリ使用を犠牲にしてソートを行う。 | ||||||||||||
```python | ||||||||||||
class Solution: | ||||||||||||
def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||||||||||||
num_to_count = defaultdict(int) | ||||||||||||
for num in nums: | ||||||||||||
num_to_count[num] += 1 | ||||||||||||
|
||||||||||||
bucket = [[] for _ in range(len(nums) + 1)] | ||||||||||||
for num, freq in elements.items(): | ||||||||||||
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. 見落としてました,ありがとうございます |
||||||||||||
bucket[freq].append(num) | ||||||||||||
|
||||||||||||
sorted_nums = [] | ||||||||||||
for i in range(len(bucket) -1, 0, -1): | ||||||||||||
if bucket[i]: | ||||||||||||
sorted_nums.extend(bucket[i]) | ||||||||||||
if len(sorted_nums) >= k: | ||||||||||||
return sorted_nums[:k] | ||||||||||||
Comment on lines
+91
to
+92
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.
Suggested change
|
||||||||||||
``` | ||||||||||||
|
||||||||||||
# step3 | ||||||||||||
```python | ||||||||||||
class Solution: | ||||||||||||
def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||||||||||||
num_to_count = defaultdict(int) | ||||||||||||
for num in nums: | ||||||||||||
num_to_count[num] += 1 | ||||||||||||
|
||||||||||||
sorted_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. 厳密にはsortedでない違和感を感じました。 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. 同じ感想を持ちました。(heapq で使われている)min-heap では root が最小値であることが保証されているだけなので sorted とは言えなさそうです |
||||||||||||
for num, freq in num_to_count.items(): | ||||||||||||
heapq.heappush(sorted_nums, (freq, num)) | ||||||||||||
|
||||||||||||
top_k_freq = [] | ||||||||||||
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文の下に書いていいと思いました。 |
||||||||||||
while(len(sorted_nums) > k): | ||||||||||||
heapq.heappop(sorted_nums) | ||||||||||||
|
||||||||||||
for num in sorted_nums: | ||||||||||||
top_k_freq.append(num[1]) | ||||||||||||
Comment on lines
+111
to
+112
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.
Suggested change
|
||||||||||||
|
||||||||||||
return top_k_freq | ||||||||||||
``` |
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.
if len() > k
の時点で取り出すとメモリが少なく済みそうです。