天天看点

LeetCode 347:前 K 个高频元素LeetCode 347:前 K 个高频元素

目录

  • 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;
    }
};