Top K Frequent Elements解题报告

本文详细介绍了如何解决LeetCode上的Top K 频繁元素问题,包括使用哈希表记录元素频率、利用堆排序进行高效排序,以及通过优先队列实现的完整解决方案。

https://leetcode.com/problems/top-k-frequent-elements/

这道题的意思是选择出现频率前k位的元素,开始我想的是选择排序,后来发现,选择排序是找第k大元素的方法==。

一般来说求数组出现频率最高的数字都要用map来记录数字出现的频率,然后按照出现次数再次排序。这里可以用堆排序做。所以现在要复习一下堆排序了:
堆,可以看做是一棵完全二叉树,因为完全二叉树除了最底层之外,其他层都是满的。所以堆可以用数组表现出来。

对于给定某节点的坐标i:
parent=i
left=2i
right=2i+1
二叉堆一般分为两种:最大堆和最小堆。最大堆是最大的元素在根节点,最小堆是最小的元素在根节点。

实现堆排序首先需要实现,以第i个节点为根把原始数列调整成一个大顶堆,但是这里的调整不是一次到位,而是使第i个节点成为第i个节点到数组末的这部分数组中最大的数。

void Adjust(int k[],int i,int n){
int j;
int temp=k[i];
j=2*i;
while(j<=n){
if(j<n&&k[j]<k[j+1]) j++;
if(temp>k[j]) break;
k[j/2]=k[j];
j=2*j;
}
k[j/2]=temp;
}
这一次相当于会选出i到n中最大的数,然后将这个重复n次就可以了。

void heapSort(int k[],int n){
int i;
int temp;
for(i=n/2;i>=0;i--) Adjust(k,i,n);
for(i=n-1;i>=1;i--){
temp=k[i+1];
k[i+1]=k[1];
k[1]=temp;
Adjust(k,1,i);
}
}
这道题可以用优先队列:

,优先队列在C++中的解释是:
Priority queues are a type of container adaptors, specifically designed such that its first element is always the greatest of the elements it contains, according to some strict weak ordering criterion.This context is similar to a heap, where elements can be inserted at any moment, and only the max heap element can be retrieved (the one at the top in the priority queue).Priority queues are implemented as container adaptors, which are classes that use an encapsulated object of a specific container class as its underlying container, providing a specific set of member functions to access its elements. Elements are popped from the "back" of the specific container, which is known as the top of the priority queue.

代码:

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> res;
        if(nums.size()==0) return res;
        unordered_map<int,int> mp;
        priority_queue<pair<int,int>> q;
        for(int i=0;i<nums.size();i++){
            if(mp.find(nums[i])==mp.end()) mp.insert(pair<int,int>(nums[i],1));
            else mp[nums[i]]++;
        }
        for(auto &it:mp){
            q.push({it.second,it.first});
        }
        for(int i=0;i<k;i++){
            res.push_back(q.top().second);
            q.pop();
        }
        return res;
    }
};




### 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、付费专栏及课程。

余额充值