Top K Frequent Elements

该问题要求在非空整数数组中找到出现频率最高的k个元素。解决方案可以采用映射结合最小堆的方法,同时需要自定义比较方式以确保堆中的元素是按频率降序排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a non-empty array of integers, return the k most frequent elements.

For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].

Note: 

  • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.

  • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

map加最小堆。

需要新定义比较方法。

class Solution {
    struct cmp {
        bool operator() (const pair<int,int> &a, const pair<int,int> &b)
        {
            return a.second>b.second;
        }
    };
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> ret;
        unordered_map<int ,int > Hash;
        for(int i=0; i<nums.size(); ++i){
            Hash[nums[i]]++;
        }
        priority_queue<pair<int ,int>,vector<pair<int,int>>,cmp> PQ;
        for(auto i = Hash.begin(); i != Hash.end(); ++i){
            if(PQ.size()!=k){
                PQ.push(*i);
            }
            else{
                if(i->second>PQ.top().second){
                    PQ.pop();
                    PQ.push(*i);
                }
            }
        }
        while(!PQ.empty()){
            ret.push_back(PQ.top().first);
            PQ.pop();
        }
        reverse(ret.begin(),ret.end());
        return ret;
    }
};
stl库中有partial_sort实质上也是用堆排序完成的。

### C++ 实现 Top-K 算法 Top-K 问题是常见的算法问题之一,通常用于从大量数据中找到排名靠前的 K 个元素。下面是一个完整的 C++ 示例代码及其解释。 #### 示例代码 ```cpp #include <iostream> #include <vector> #include <queue> #include <functional> using namespace std; // 定义比较函数,使得 priority_queue 成为最小堆 struct Compare { bool operator()(const pair<int, int>& a, const pair<int, int>& b) { return a.second < b.second; // 按照频率从小到大排序 } }; vector<int> topKFrequentElements(vector<int>& nums, int k) { unordered_map<int, int> frequencyMap; // 记录每个元素出现的次数 for (auto num : nums) { frequencyMap[num]++; } // 使用优先队列(最小堆)存储频率最高的 k 个元素 priority_queue<pair<int, int>, vector<pair<int, int>>, Compare> minHeap; for (auto& entry : frequencyMap) { minHeap.push({entry.first, entry.second}); if (minHeap.size() > k) { minHeap.pop(); // 移除堆顶元素(频率最低) } } vector<int> result; while (!minHeap.empty()) { result.push_back(minHeap.top().first); // 提取堆中的元素 minHeap.pop(); } reverse(result.begin(), result.end()); // 结果按频率降序排列 return result; } int main() { vector<int> nums = {1, 1, 1, 2, 2, 3}; int k = 2; vector<int> result = topKFrequentElements(nums, k); cout << "Top-" << k << " frequent elements: "; for (auto elem : result) { cout << elem << " "; } cout << endl; return 0; } ``` --- ### 代码详解 1. **输入准备** - 输入数组 `nums` 是待处理的数据集。 - 参数 `k` 表示需要找出的最高频次的元素数量。 2. **构建频率表** - 使用 `unordered_map<int, int>` 存储每个元素的出现次数[^1]。 - 遍历整个数组,统计每个元素的频率。 3. **使用最小堆筛选 Top-K 元素** - 创建一个自定义比较规则的小根堆(`priority_queue`),其中堆顶是最不频繁的元素。 - 遍历频率表,将元素插入堆中。如果堆的大小超过了 `k`,则弹出堆顶元素(即频率最低的元素)。 4. **提取结果** - 堆中剩余的元素就是频率最高的 `k` 个元素。 - 将这些元素依次取出并存入结果向量中。 5. **输出结果** - 输出最终的 Top-K 频繁元素列表。 --- ### 性能分析 - **时间复杂度**: - 统计频率阶段:\( O(n) \),其中 \( n \) 是数组长度。 - 构建堆阶段:每次插入或删除操作的时间复杂度为 \( O(\log{k}) \),总共最多进行 \( m \) 次(m 为不同元素的数量)。因此这一部分的时间复杂度为 \( O(m \cdot \log{k}) \)[^1]。 - 整体时间复杂度为 \( O(n + m \cdot \log{k}) \)。 - **空间复杂度**: - 主要由频率表和堆占用的空间决定,分别为 \( O(m) \) 和 \( O(k) \)。整体空间复杂度为 \( O(m + k) \)。 --- ### 示例运行 假设输入数组为 `{1, 1, 1, 2, 2, 3}`,参数 `k=2`: - 频率表为:`{1 -> 3, 2 -> 2, 3 -> 1}` - 最小堆逐步变化过程: - 插入 `(1, 3)` → 堆为 `[(1, 3)]` - 插入 `(2, 2)` → 堆为 `[(2, 2), (1, 3)]` - 插入 `(3, 1)` 并移除堆顶 `(3, 1)` → 堆为 `[(2, 2), (1, 3)]` - 最终结果为 `[1, 2]`。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值