347. 前 K 个高频元素

347. 前 K 个高频元素

1.题目描述

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
在这里插入图片描述
示例 2:
在这里插入图片描述
说明:
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

2.方法1(桶排序)

首先使用哈希表统计数组元素的频率,统计完成后,创建一个二维数组,将频率作为数组第一个维度的下标,将元素作为第二个维度的值,当出现不同的元素频率相同时,直接添加到第二个维度即可。倒序遍历二维数组,区前K个高频元素。

3.代码

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) { 
        unordered_map<int, int> m;
        for(auto & num : nums){
            m[num]++;
        }
        //二维数组第一维下标是数字出现的频率
        vector<vector<int>> buckets(nums.size()+1);
        for(auto iter = m.begin();iter != m.end();++iter){
            buckets[iter->second].push_back(iter->first);//元素频率作为下标,元素作为值,如果两个元素的频率相同,则加入数组第二维
        }
        vector<int> res(k);
        int count = 0;//记录是第几高的频率
        //将buckets前k个高频元素放入res中
        for(int i = buckets.size() - 1;i >= 0;--i){
            for(int j = 0;j < buckets[i].size();++j){//取出每个频率的元素
                res[count] = buckets[i][j];
                if(++count == k){
                    return res;
                }
            }
        }
        return res;
    }
};

4.复杂度分析

时间复杂度:O(n),n 表示数组的长度。首先,遍历一遍数组统计元素的频率,这一系列操作的时间复杂度是 O(n);桶的数量为 n + 1,所以桶排序的时间复杂度为 O(n);因此,总的时间复杂度是 O(n)。
空间复杂度:O(n)

5.方法2(快速选择)

用哈希表保存数组每个元素出现的频率,把元素和相应的频率构造成pair<int,int>保存到vector中,对vector进行倒序排序,排序标准时元素的频率。把第K高的频率移动到正确的位置,则K之前的元素的频率都大于第K个元素的频率,把这部分元素存入结果数组res中。

6.代码

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> m;
        for(auto &num : nums){
            m[num]++;
        }
        vector<pair<int,int>> data(m.begin(),m.end());
        int left= 0;
        int right = data.size()-1;
        int index = partiton(data,left,right);
        while(index != k-1){
            if(index > k-1){
                right = index - 1;
            }
            else{
                left = index + 1;
            }
            index = partiton(data,left,right);
        }
        vector<int> res;
        for(int i = 0;i < k;++i){
            res.push_back(data[i].first);
        }
        return res;
    }
    int partiton(vector<pair<int,int>>& nums,int left,int right){
        int t = left;
        for(int i = left;i < right;++i){
            if(nums[i].second > nums[right].second){
                swap(nums[t++],nums[i]);
            }
        }
        swap(nums[t],nums[right]);
        return t;
    }
};

7.复杂度分析

时间复杂度:O(n)
空间复杂度:O(n)

发布了146 篇原创文章 · 获赞 0 · 访问量 2951

猜你喜欢

转载自blog.csdn.net/jiangdongxiaobawang/article/details/104320490