347. 前 K 个高频元素
中等
1.6K
相关企业
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
1 <= nums.length <= 105
k
的取值范围是[1, 数组中不相同的元素的个数]
- 题目数据保证答案唯一,换句话说,数组中前
k
个高频元素的集合是唯一的
扫描二维码关注公众号,回复:
16374579 查看本文章
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n)
,其中 n
是数组大小。
先上C++版本的,基本思路是用hashmap统计出现的次数,然后维护一个大小为K的最小堆,最小堆的比较函数使用频率作为比较量。最后,遍历这个最小堆就可以了。其中用到了自定义的pair数据和比较函数。
class Solution {
typedef pair<int,int> PSI;
struct cmp
{
bool operator()(PSI a, PSI b)
{
return a.second>b.second; // 最小堆
}
};
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
priority_queue<PSI,vector<PSI>,cmp> pq;
int n=nums.size();
unordered_map<int,int> Hashmap;
for(int i=0;i<n;i++)
{
Hashmap[nums[i]]++;
}
for (auto iter = Hashmap.begin(); iter != Hashmap.end(); ++iter)
{
if(pq.empty() || pq.size()<k){
pq.push({iter->first,iter->second});
}
else if(pq.size()>=k){
int front = pq.top().first; //key
int end = pq.top().second; //value
if(iter->second>end){
pq.pop();
pq.push({iter->first,iter->second});
}
}
}
vector<int>ans;
while(!pq.empty())
{
ans.push_back(pq.top().first);
pq.pop();
}
return ans;
}
};
使用kotlin的话,采用如下解法:
解题思路:
- 首先统计每个元素出现的频率,使用哈希表进行统计,其中键为元素值,值为出现次数。
- 将哈希表中的键值对转化为元素值和出现次数的对应关系的列表。
- 对列表按照出现次数进行降序排序。
- 取出前 k 个元素的值并返回。
该算法的时间复杂度为 $O(n \log n)$,其中 $n$ 是数组的长度。哈希表的插入操作的时间复杂度为 $O(1)$,排序的时间复杂度为 $O(n \log n)$,取出前 k 个元素的时间复杂度为 $O(k)$。空间复杂度为 $O(n)$。
class Solution {
fun topKFrequent(nums: IntArray, k: Int): IntArray {
val map = mutableMapOf<Int, Int>()
for (num in nums) {
map[num] = map.getOrDefault(num, 0) + 1
}
val list = mutableListOf<Pair<Int, Int>>()
for (entry in map.entries) {
list.add(Pair(entry.key, entry.value))
}
list.sortByDescending { it.second }
val result = mutableListOf<Int>()
for (i in 0 until k) {
result.add(list[i].first)
}
return result.toIntArray()
}
}
使用kotlin就充分使用了各种数据直接的转换和库函数,写起来确实简明多了。