题目:
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
https://leetcode.cn/problems/top-k-frequent-elements/
方法一:
class Solution { public: vector<int> topKFrequent(vector<int>& nums, int k) { // 创建一个哈希表,用于记录每个元素出现的频率 unordered_map<int, int> freqNum; for (int num : nums) { freqNum[num]++; } // 创建一个最小堆,用于存储频率及其对应的元素 // 优先队列的比较函数为 greater<>,表示最小堆 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 遍历哈希表,将频率和元素加入最小堆 for (auto& entry : freqNum) { pq.emplace(entry.second, entry.first); // 如果堆的大小超过 k,弹出堆顶元素(最小频率) if (pq.size() > k) { pq.pop(); } } // 从堆中取出元素,构成结果向量 vector<int> result(k); int i = k-1; while (!pq.empty()) { result[i]=pq.top().second; pq.pop(); i--; } return result; } }; /*这段代码实际上使用了最小堆来维护前 k 高的频率元素。首先,通过哈希表 valToFreq 统计每个元素的频率。然后,使用一个最小堆 pq,将频率和元素对加入堆中。如果堆的大小超过 k,则弹出堆顶元素,以保持堆中始终只有前 k 高的频率元素。*/
方法二:
-
统计频率: 遍历给定的整数数组,使用一个哈希表记录每个元素出现的频率。
-
构建数据结构: 创建一个向量,将哈希表中的每个元素及其频率存储为键值对(pair)并添加到向量中。
-
构建最大堆: 通过构建一个最大堆来找到频率最高的 k 个元素。最大堆的根节点具有最大的频率。
-
填充最大堆: 遍历向量中的每个键值对,将它们添加到最大堆中。如果堆的大小超过 k,弹出堆顶元素,以保持堆中只有前 k 高的频率元素。
-
提取结果: 从最大堆中弹出 k 个元素,这些元素就是出现频率前 k 高的元素。
-
反转结果: 因为最大堆保证了堆顶元素是频率最高的元素,但是问题要求按任意顺序返回结果,所以最后我们需要将结果向量反转。
class Solution { public: // 最大堆化函数,用于维护堆的性质 void heapMax(vector<pair<int, int>>& uniqueNum, int n, int i) { int leftChild = 2 * i + 1; int rightChild = 2 * i + 2; int maxChild = i; // 如果左子节点存在且比当前节点的频率大,则更新最大子节点 if (leftChild < n && uniqueNum[leftChild].second > uniqueNum[maxChild].second) { maxChild = leftChild; } // 如果右子节点存在且比当前节点的频率大,则更新最大子节点 if (rightChild < n && uniqueNum[rightChild].second > uniqueNum[maxChild].second) { maxChild = rightChild; } // 如果最大子节点不是当前节点,则交换节点并递归调整 if (maxChild != i) { swap(uniqueNum[i], uniqueNum[maxChild]); heapMax(uniqueNum, n, maxChild); } } // 构建最大堆函数 void buildHeap(vector<pair<int, int>>& uniqueNum) { int n = uniqueNum.size(); int last_node = n - 1; int parent = last_node / 2; // 从最后一个非叶子节点开始向上构建最大堆 for (int i = parent; i >= 0; i--) { heapMax(uniqueNum, n, i); } } vector<int> topKFrequent(vector<int>& nums, int k) { unordered_map<int, int> freqNums; // 统计每个元素的频率 for (int i = 0; i < nums.size(); i++) { freqNums[nums[i]]++; } vector<pair<int, int>> uniqueNum; // 将频率和元素值存储为 pair 放入 uniqueNum 中 for (const auto& entry : freqNums) { uniqueNum.push_back(make_pair(entry.first, entry.second)); } // 构建最大堆 buildHeap(uniqueNum); vector<int> result; int n = uniqueNum.size(); // 从堆中取出前 k 高频元素 for (int i = n - 1; i >= n - k; i--) { result.push_back(uniqueNum[0].first); swap(uniqueNum[0], uniqueNum[i]); heapMax(uniqueNum, i, 0); } return result; } };
浙公网安备 33010602011771号