diff --git a/347. Top K Frequent Elements.md b/347. Top K Frequent Elements.md new file mode 100644 index 0000000..86596f9 --- /dev/null +++ b/347. Top K Frequent Elements.md @@ -0,0 +1,113 @@ +URL: https://leetcode.com/problems/top-k-frequent-elements/description/ + +# Step 1 + +- 実装時間: 5分 +- 時間計算量: O(n log n) +- 空間計算量: O(n) + +kは条件で負の数は入ってこないので、バリデーションはしない。 + +```python +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + count_frequency = {} + for num in nums: + if num in count_frequency: + count_frequency[num] += 1 + else: + count_frequency[num] = 1 + + top_k_elements = [] + for key, value in sorted(count_frequency.items(), key=lambda x:x[1], reverse=True)[:k]: + top_k_elements.append(key) + + return top_k_elements +``` + +後半は1行でかけると気づいた。 + +```python +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + count_frequency = {} + for num in nums: + if num in count_frequency: + count_frequency[num] += 1 + else: + count_frequency[num] = 1 + return list(map(lambda x:x[0], sorted(count_frequency.items(), key=lambda x:x[1], reverse=True)[:k])) +``` + +# Step 2 + +- 参考にした + - https://github.com/tarinaihitori/leetcode/pull/9 + - https://github.com/thonda28/leetcode/pull/17 + - https://github.com/colorbox/leetcode/pull/24 + - https://github.com/rihib/leetcode/pull/20 + - https://github.com/hroc135/leetcode/pull/10 + - https://github.com/hayashi-ay/leetcode/pull/60/ + - https://github.com/kazukiii/leetcode/pull/10 + - https://github.com/wf9a5m75/leetcode3/pull/3 + - https://github.com/Yoshiki-Iwasa/Arai60/pull/8 + - https://github.com/kagetora0924/leetcode-grind/pull/11 + - https://github.com/seal-azarashi/leetcode/pull/9 + +- 変数の名前 + - num_to_count のように、変数にどのような値が含まれているかを想像できるような変数名にしたほうが良い + - https://github.com/colorbox/leetcode/pull/24/files#r1740739103 + - 変数名のnums_frequencyですが、整数に対して頻度なので、num_to_freqencyとかのほうが分かりやすい + - https://github.com/Ryotaro25/leetcode_first60/pull/10/files#r1623225196 + + +- 別のパターン + - `dict()`のかわりに`defaultdict()`をつかう + - https://github.com/thonda28/leetcode/pull/17/files#r1769492893 + - top kを選ぶときにheapqを使う。 + - バケットソートを使う + - https://github.com/kazukiii/leetcode/pull/10#discussion_r1639979474 + +- lambda関数を使ってる人がいなかった。 + - 他の人のコードと見比べると、Step1では`x`が急に出てきているので、わかりにくくてよくない気がした。 + - そもそも内包表記でかける + - `return [ num for count, num in top_k_frequent]` + +- 問題設定は必ず k 種類あることになっていますが、なかった場合にどうするかは考えておいてください。 +特別な値を返すか、Exception を投げるか、短いものでも返すか、プログラムを止めるか、そのあたりです。 + - https://github.com/tarinaihitori/leetcode/pull/9/files#r1816996368 + +```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 + + top_k_frequent = [] + for num, count in num_to_count.items(): + heappush(top_k_frequent, (count, num)) + if len(top_k_frequent) > k: + heappop(top_k_frequent) + return [num for count, num in top_k_frequent] +``` + +# Step 3 + +- 時間計算量: O(n log k) +- 空間計算量: O(n) + +```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 + + top_k_frequent = [] + for num, count in num_to_count.items(): + heappush(top_k_frequent, (count, num)) + if len(top_k_frequent) > k: + heappop(top_k_frequent) + return [num for _, num in top_k_frequent] +```