0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

9. Top K Frequent Elements

Last updated at Posted at 2024-12-24

問題:
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.

いきなりheapに飛びつくのはいただけない!

1 リストをソート

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        values_to_frequency = {}
        for num in nums:
            values_to_frequency[num] = values_to_frequency.get(num, 0) + 1
        
        frequent_values = []
        for value, frequency in values_to_frequency.items():
            frequent_values.append((value, frequency))
        frequent_values.sort(reverse=True, key=lambda value_frequency: value_frequency[1])

        if k < len(frequent_values):
            frequent_values = frequent_values[:k]
        
        return [value for value, _ in frequent_values]

2 heap

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        values_to_frequency = {}
        for num in nums:
            values_to_frequency[num] = values_to_frequency.get(num, 0) + 1
        
        frequent_values = []  #heap
        for value, frequency in values_to_frequency.items():
            heapq.heappush(frequent_values, (frequency, value))
            while k < len(frequent_values):
                heapq.heappop(frequent_values)
        
        return [value for _, value in frequent_values]

飛びついてもいいんだが、あなたこれどう解きますかと聞かれてheapしか出てこなかったら怖いなと思う。

3 bucket

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        values_to_frequency = {}
        for num in nums:
            values_to_frequency[num] = values_to_frequency.get(num, 0) + 1
        
        max_frequency = 10**5
        frequency_bucket = [[] for _ in range(max_frequency+1)]  #bucket frequency_bucket[v]: values which appear v times
        for value, frequency in values_to_frequency.items():
            frequency_bucket[frequency].append(value)
        
        top_k_values = []
        for i in range(len(frequency_bucket)-1,  -1, -1):
            top_k_values.extend(frequency_bucket[i])
            if len(top_k_values) >= k:
                break
        
        return top_k_values

使用メモリーが無駄にでかい。
マジックナンバーは使いたくないから変数初期化しとく。あと、変数の命名にデータ構造の名前入れるのってどうなんですかね?僕はあんまり好きじゃないんですが。

4 Quick Select

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        def quick_select(left, right):
            pivot_index = random.randint(left, right)
            pivot = values[pivot_index]
            pivot_frequency = values_to_frequency[pivot]
            values[pivot_index], values[right] = values[right], values[pivot_index]

            partition_index = left
            for i in range(left, right):
                if values_to_frequency[values[i]] > pivot_frequency:
                    values[i], values[partition_index] = values[partition_index], values[i]
                    partition_index += 1
            values[partition_index], values[right] = values[right], values[partition_index]

            if partition_index == k - 1:
                return None
            elif partition_index > k - 1:
                return quick_select(left, partition_index - 1)
            elif partition_index < k - 1:
                return quick_select(partition_index + 1, right)
        
        values_to_frequency = {}
        for num in nums:
            values_to_frequency.setdefault(num, 0)
            values_to_frequency[num] += 1

        values = list(values_to_frequency.keys())
        
        quick_select(0, len(values) - 1)

        return values[:k]

平均時間計算量: O(n) 最悪計算量: O(n^2) 空間計算量: O(1)
まぁコールスタックがかかりますが。制約条件からしてスタックオーバーフローしそうな匂いもしましたが、末尾最適化を信じます。
あと、sortの方が早いらしいです。開発者が無駄な処理をしないようにチューニングしてくれていて、かつネイティブコードで動作するからです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?