-
Notifications
You must be signed in to change notification settings - Fork 0
347: Top K Frequent Elements #11
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,67 @@ | ||||||||||||||
| ## step1 | ||||||||||||||
| - pythonのCounterでできないのか? | ||||||||||||||
| - Counter.most_common()でできそう | ||||||||||||||
| - https://github.com/python/cpython/blob/a8e814db96ebfeb1f58bc471edffde2176c0ae05/Lib/collections/__init__.py#L571 | ||||||||||||||
| - 内部で_heapq.nlargestを使っており、計算量はO(nlogk) | ||||||||||||||
|
|
||||||||||||||
| ```py | ||||||||||||||
| for num, _count in counter.most_common(): | ||||||||||||||
| frequent_nums.append(num) | ||||||||||||||
| if len(frequent_nums) == k: | ||||||||||||||
| break | ||||||||||||||
|
Comment on lines
+8
to
+11
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. Counter.most_common()メソッドのオプショナルな引数nで上位n個だけにできるので、使うとif-breakのところが無くせてシンプルです。
Suggested change
https://docs.python.org/3/library/collections.html#collections.Counter.most_common こう書くなら、内包表記にしてもいいですね。趣味の範囲です。 class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
counter = Counter(nums)
return [num for num, _ in counter.most_common(k)] |
||||||||||||||
| ``` | ||||||||||||||
| - 上記のように書いたが、forのindexをとるときは普段enumerateを使うようにしているが、今回の場合は下記のようになり少しわかりにくいかなと思って上記にした | ||||||||||||||
|
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. 自分も上の方がわかりやすいと感じます。 簡単なものさしとして、変数は減らせるだけ減らすのはわりと有効な気がします。(もちろん例外もありますが。) |
||||||||||||||
|
|
||||||||||||||
| ```py | ||||||||||||||
| for index, (num, _count) in enumerate(counter.most_common()): | ||||||||||||||
| frequent_nums.append(num) | ||||||||||||||
| if index == k - 1: | ||||||||||||||
| break | ||||||||||||||
|
|
||||||||||||||
| return frequent_nums | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ## step2 | ||||||||||||||
| 自分としては気になるところはないので、他の人のコードを見る | ||||||||||||||
| - https://github.com/Hiroto-Iizuka/coding_practice/pull/9/files | ||||||||||||||
| - 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.
というより、じゃあ |
||||||||||||||
| - defaultdictに入れてvalueでkeyをsortして出すのも良いかも | ||||||||||||||
| - dictの命名は大抵の場合key_to_valueがわかりやすい!!! | ||||||||||||||
| - https://github.com/mamo3gr/arai60/pull/9/files | ||||||||||||||
| - コメント集のまとめが勉強になった | ||||||||||||||
| - コメント集をどのstepで読むか迷うがどこかでは読みたい | ||||||||||||||
| - `sorted(num_count, key=num_count.get)`の書き方は初めて見た。。。毎回lambda式を調べていた | ||||||||||||||
| - https://github.com/Yuto729/LeetCode_arai60/pull/15/files | ||||||||||||||
| - step2のheapのとこは文言で見ると難しそうでわかんなかった | ||||||||||||||
| - https://github.com/naoto-iwase/leetcode/pull/9/files | ||||||||||||||
| - 上のさっきのstep2解法だと思うが、見たらわかりやすかった | ||||||||||||||
| - 大きい順だと対応できないので-をつけてやる方法は`min-heap`という名前がついてるみたい | ||||||||||||||
| - `defaultdictではなく[Counter](https://docs.python.org/ja/3.13/library/collections.html#collections.Counter)のが適していそう。そう思う理由は今のところ、カウント用途に特化したクラスだから良さそう、というくらいしかない。` | ||||||||||||||
| - 自分は出現回数を数えるといえばと思ってほぼ何も考えず飛びついてしまったので何で適しているかは言語化していきたい | ||||||||||||||
| - クイックソートについて知っていなくてはいけないことは下記のようだが、計算量がO(NlogN)であることしか知らない。。。 | ||||||||||||||
| - 最悪・平均計算量 | ||||||||||||||
| - 末尾再帰最適化 | ||||||||||||||
| - ピボット選択 | ||||||||||||||
| - マージソートとのプロコン | ||||||||||||||
| - このかたのmemoはすごいが、自分の力量だとここまですると1問につき1年かかるので、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. 私、「マージソートとのプロコン」という言葉に、ソートの安定性やメモリーアクセスの局所性などを詰め込んでいます。本当は、中身を詳しく書いたほうがいいですね。 |
||||||||||||||
| - https://github.com/t-ooka/leetcode/pull/15/files | ||||||||||||||
| - たくさんの解法がおさえてありすごい | ||||||||||||||
| - いくつか自分も思いついた際は書けるようにしたい | ||||||||||||||
|
|
||||||||||||||
| - defaultdictを使った解放にする | ||||||||||||||
| - 時間計算量はmをユニークな要素数としてO(n) + O(mlogm) | ||||||||||||||
| - 最悪時間計算量はO(nlogn)(ほぼmがnになるので) | ||||||||||||||
| - 空間計算量はO(m) | ||||||||||||||
|
|
||||||||||||||
| ## step3 | ||||||||||||||
| - defaultdictの初期値(今回はint)を忘れない | ||||||||||||||
| - key=~getの書き方はすっきりしているので毎回調べず書けるようになりたい | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| ## TODO | ||||||||||||||
| [] クイックソートについて | ||||||||||||||
|
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. コーディング練習会の本筋ではないですが、Markdownのチェックボックスは箇条書きでないとレンダリングされないようです。
Suggested change
|
||||||||||||||
| - 最悪・平均計算量 | ||||||||||||||
| - 末尾再帰最適化 | ||||||||||||||
| - ピボット選択 | ||||||||||||||
| - マージソートとのプロコン | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # | ||
| # @lc app=leetcode id=347 lang=python3 | ||
| # | ||
| # [347] Top K Frequent Elements | ||
| # | ||
| from collections import Counter | ||
|
|
||
|
|
||
| # @lc code=start | ||
| class Solution: | ||
| def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||
| counter = Counter(nums) | ||
| frequent_nums = [] | ||
|
|
||
| for num, _count in counter.most_common(): | ||
| frequent_nums.append(num) | ||
| if len(frequent_nums) == k: | ||
| break | ||
|
|
||
| return frequent_nums | ||
|
|
||
|
|
||
| # @lc code=end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # | ||
| # @lc app=leetcode id=347 lang=python3 | ||
| # | ||
| # [347] Top K Frequent Elements | ||
| # | ||
|
|
||
| from collections import defaultdict | ||
|
|
||
|
|
||
| # @lc code=start | ||
| class Solution: | ||
| def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||
| num_to_frequency = defaultdict(int) | ||
| for num in nums: | ||
| num_to_frequency[num] += 1 | ||
|
|
||
| num_frequent_order = sorted( | ||
| num_to_frequency, key=num_to_frequency.get, reverse=True | ||
| ) | ||
|
|
||
| return num_frequent_order[:k] | ||
|
|
||
|
|
||
| # @lc code=end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # | ||
| # @lc app=leetcode id=347 lang=python3 | ||
| # | ||
| # [347] Top K Frequent Elements | ||
| # | ||
|
|
||
| from collections import defaultdict | ||
|
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. [fyi] 例えばGoogleのスタイルガイドでは、ここでは
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. もちろんGoogleのスタイルガイドが絶対ではありません。メリット・デメリットを把握しつつ、自分が取るスタイルを決めると良いと思います。 (私も個人的には、コード本体が長くなりがちなのでこのような短いimportの方が好きです) |
||
|
|
||
|
|
||
| # @lc code=start | ||
| class Solution: | ||
| def topKFrequent(self, nums: List[int], k: int) -> List[int]: | ||
| num_to_frequency = defaultdict(int) | ||
| for num in nums: | ||
| num_to_frequency[num] += 1 | ||
|
|
||
| num_frequency_order = 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. たしかに、nums_ordered_by_frequencyとかだとかなり丁寧な印象ですね。 |
||
| num_to_frequency, key=num_to_frequency.get, reverse=True | ||
| ) | ||
|
|
||
| return num_frequency_order[:k] | ||
|
|
||
|
|
||
| # @lc code=end | ||
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.
確かに、たとえばPEP8では
countが予約語ならcount_のようによける書き方がありますが、countは予約語では無いのでそのまま書いて大丈夫かなと思いました。https://peps.python.org/pep-0008/#function-and-method-arguments
あるいは使わないループ変数という意図であれば
_で潰すと良いと思います。