LeetCode 347:前 K 个高频元素

LeetCode 347:前 K 个高频元素

题目描述

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

示例 1:

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

示例 2:

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

提示:

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

解题

哈希+排序

    最直接的思路应该是对整个数组进行排序,这样相同的数字相邻,可以很轻松的统计每个数字出现的次数,但是算法要求复杂度优于 O ( n l o g n ) O(nlogn) O(nlogn),所以直接排序是不可行的。但还是要统计每个整数的频率,不能排序,那么可以借助哈希表,这样不用考虑数值范围和各种取值可能。统计好之后按照次数再排序即可。

class Solution {
public:    
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> nums_counts;
        for (auto &i : nums)
            ++nums_counts[i];
        
        vector<pair<int,int>> nums_counts_sort(nums_counts.begin(), nums_counts.end());
        sort(nums_counts_sort.begin(), nums_counts_sort.end(), [](pair<int, int> &a, pair<int, int> &b) { return a.second > b.second; });
        
        vector<int> topKF_nums(k, 0);
        for (int i=0; i < k; ++i)
            topKF_nums[i] = nums_counts_sort[i].first;
        return topKF_nums;
    }
};

哈希+优先队列

    思路与哈希+排序本质是一致的,只不过借助优先队列来排序和控制选择的数目,优先队列按照统计数从小到大存储<统计数-数字>这一数对。统计好数字出现的次数之后,对哈希表进行遍历,如果优先队列的大小小于k,则不断将<统计数-数字>压入队列中,如果优先队列大小等于k,且队列顶部元素统计数小于当前元素统计数,则将顶部元素弹出,将该元素压入队列;如果队列顶部元素统计数不小于当前元素统计数,则继续向前迭代。

class Solution {
public:    
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> nums_counts;
        for (auto &i : nums)
            ++nums_counts[i];
        
        priority_queue< pair<int,int>, vector<pair<int, int>>, greater< pair<int,int> > > pq;
        
        for (auto &p : nums_counts){
            if (pq.size()==k){
                if (pq.top().first < p.second){
                    pq.pop();
                    pq.push(make_pair(p.second, p.first));
                }
            }
            else
                pq.push(make_pair(p.second, p.first));
        }
        
        vector<int> topKF_nums(k, 0);
        while (k){
            topKF_nums[--k] = pq.top().second;
            pq.pop();
        }
            
        return topKF_nums;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值