【LeetCode-哈希表】前 K 个高频元素

题目描述

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

输入: nums = [1], k = 1
输出: [1]

说明:

  • 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
  • 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
  • 你可以按任意顺序返回答案。

题目链接: https://leetcode-cn.com/problems/top-k-frequent-elements/

思路1

用哈希表统计每个元素出现的次数,然后根据次数创建一个新的二维数组 v,下标为每个元素出现的次数。例如,v[cnt] = [1,2] 的含义是 1, 2 分别出现了 cnt 次,然后从后往前遍历二维数组 v,如果 v[i] 不空,就将 v[i] 中的元素放进答案中,直到答案中已经包含了 k 个元素。代码如下:

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        if(nums.empty()) return {};

        unordered_map<int, int> hash;
        for(int i=0; i<nums.size(); i++){
            hash[nums[i]]++;
        }

        vector<vector<int>> v(nums.size()+1);
        auto it = hash.begin();
        for(; it!=hash.end(); it++){
            int key = it->first;
            int value = it->second;
            v[value].push_back(key);
        }

        vector<int> ans;
        for(int i=v.size()-1; i>=0 && ans.size()<k; i--){
            if(!v[i].empty()){
                for(int j=0; j<v[i].size(); j++) ans.push_back(v[i][j]);
            }
        }
        return ans;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

思路2

思路 2 整体上和思路 1 是一样的,首先用哈希表统计各元素出现的频率,然后使用小根堆来替代思路 1 中的二维数组,可以使用 stl 中的优先队列 priority_queue 来模拟小根堆。小根堆的定义为priority_queue<pair<int, int>> q,pair 的第二个值为元素,第一个值为该元素出现的频率,因为 priority_queue 默认按照 pair 的第一个值降序排序。将优先队列中的元素出队列,并将队头节点pair 的第二个值放进答案中(第二个值就是数组中的元素,第一个值为出现次数)。代码如下:

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        if(nums.empty()) return {};

        unordered_map<int, int> hash;
        for(int i=0; i<nums.size(); i++){
            hash[nums[i]]++;
        }

        priority_queue<pair<int, int>> q;
        auto it = hash.begin();
        for(; it!=hash.end(); it++){
            q.push(make_pair(it->second, it->first));
        }

        vector<int> ans;
        while(!q.empty() && ans.size()<k){
            auto item = q.top(); q.pop();
            ans.push_back(item.second);
        }
        return ans;
    }
};

关于按照 pair 中第一个元素升序还是降序排列的问题可以参考这篇文章

  • 时间复杂度:O(nlogk)
  • 空间复杂度:O(n)
posted @ 2020-05-22 22:38  Flix  阅读(144)  评论(0编辑  收藏  举报