力扣刷题:前 K 个高频元素(java实现)
Posted 谦谦均
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣刷题:前 K 个高频元素(java实现)相关的知识,希望对你有一定的参考价值。
题目:给你一个整数数组 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
个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。
相关标签:、数组
、哈希表
、分治
、桶排序
、计数
、快速选择
、排序
、堆(优先队列)
解析:题目要求输出频率最高的前k个,一般看到前几个就可以考虑用堆来实现。大概构思一下,可以先用map
键值对来记录数组中每个元素和该元素在数组中出现的频率,然后将这些元素放到有限队列中,取出前k
个。具体代码如下所示:
public int[] topKFrequent(int[] nums, int k)
//定义一个map集合来存储元素和对应的频率
Map<Integer,Integer> map = new HashMap<>();
//for循环遍历数组,统计频率
for (int num : nums)
//这个方法是判断这个元素在不在map里面,在的话就用该元素,不在就用0代替
map.put(num,map.getOrDefault(num,0)+1);
//创建一个有限队列,参数为降序排序
PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((a,b)->b[1]-a[1]);
//对map集合进行遍历,根据频率的大小将所有元素存储到有限队列中
for (int key : map.keySet())
priorityQueue.add(new int[]key,map.get(key));
int[] arr = new int[k];
for (int i = 0; i < k; i++)
//弹出频率最高的元素,并存到数组中
arr[i] = priorityQueue.poll()[0];
return arr;
Java
优先队列简介:
Java
中PriorityQueue
实现了Queue
接口,不允许放入null元素;其通过堆实现,具体说是通过完全二叉树(complete binary tree
)实现的小顶堆(任意一个非叶子节点的权值,都不大于其左右子节点的权值),也就意味着可以通过数组来作为PriorityQueue
的底层实现。
常用方法如下:
add(E e)
和offer(E e)
的语义相同,都是向优先队列中插入元素,前者在插入失败时抛出异常,后则则会返回false
。对于PriorityQueue
这两个方法其实没什么差别。element()
和peek()
的语义完全相同,都是获取但不删除队首元素,也就是队列中权值最小的那个元素,二者唯一的区别是当方法失败时前者抛出异常,后者返回null。根据小顶堆的性质,堆顶那个元素就是全局最小的那个;由于堆用数组表示,根据下标关系,0下标处的那个元素既是堆顶元素。所以直接返回数组0下标处的那个元素即可。remove(Object o)
方法用于删除队列中跟o
相等的某一个元素(如果有多个相等,只删除一个),该方法不是Queue
接口内的方法,而是Collection
接口的方法。由于删除操作会改变队列结构,所以要进行调整;又由于删除元素的位置可能是任意的,所以调整过程比其它函数稍加繁琐。
心中有梦,眼里有光。
以上是关于力扣刷题:前 K 个高频元素(java实现)的主要内容,如果未能解决你的问题,请参考以下文章