LeetCode-347. 前 K 个高频元素
题目来源
347. 前 K 个高频元素
题目详情
给你一个整数数组 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
是数组大小。
题目解析
解法一:快速排序
- 从本题的题目就可以看出,这是一个top-k问题,遇到这个问题就应该首先想到快速排序。
- 与传统快速排序不同的是,这里要求解的是出现最高评率的top-k个数,所以这里可以额外构建一个类或者结构体来存放二元值。
- 此外,还需要注意的问题就是快速排序代码的编写,有一些边界情况需要注意。
class Solution {
class NumFre{
int num;
int frq;
NumFre(){}
NumFre(int _num, int _frq){
num = _num;
frq = _frq;
}
}
public int[] topKFrequent(int[] nums, int k) {
HashMap map = new HashMap<>();
int n = nums.length;
for(int i=0; i entry : map.entrySet()){
fre[i++] = new NumFre(entry.getKey(), entry.getValue());
}
quicksort(fre, 0, fre.length -1, k);
int[] res = new int[k];
for(i=0; i right)
return;
int mid = partition(nums, left, right);
if(mid == k-1){
return;
}
if(mid > k){
quicksort(nums, left, mid-1, k);
}else{
quicksort(nums, mid+1, right, k);
}
}
private int partition(NumFre[] nums, int left, int right){
NumFre base = new NumFre(nums[left].num, nums[left].frq);
while(left < right){
while(left < right && nums[right].frq <= base.frq){
right--;
}
if(right > left){
copyObjectArrayEle(nums[left] , nums[right]);
left++;// 容易忽略
}
while(left < right && nums[left].frq >= base.frq){
left++;
}
if(left < right){
copyObjectArrayEle(nums[right], nums[left]);
right--;
}
}
copyObjectArrayEle(nums[left] , base);
return left;
}
private void copyObjectArrayEle(NumFre numsi, NumFre numsj){
numsi.num = numsj.num;
numsi.frq = numsj.frq;
}
}
解法二:堆排序
- top-k的另一个更加直观的解法是使用堆排序。
- 利用java里面的优先队列维护一个小根堆,保证优先队列里的始终是前k大的数。
class Solution {
class NumFre{
int num;
int frq;
NumFre(){}
NumFre(int _num, int _frq){
num = _num;
frq = _frq;
}
}
public int[] topKFrequent(int[] nums, int k) {
HashMap map = new HashMap<>();
int n = nums.length;
for(int i=0; i prique = new PriorityQueue<>((o1, o2) ->{
return o1.frq - o2.frq;// 构造小顶堆
});
for(Map.Entry entry : map.entrySet()){
NumFre fre = new NumFre(entry.getKey(), entry.getValue());
int size = prique.size();
if(size < k){
prique.offer(fre);
}else if(size == k){
if(fre.frq > prique.peek().frq){
prique.poll();
prique.offer(fre);
}
}
}
int[] res = new int[k];
int i=0;
while(!prique.isEmpty()){
NumFre fre = prique.poll();
res[i++] = fre.num;
}
return res;
}
}