一、题目描述
给定一个整数数组 nums 和一个整数 k ,请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
二、代码思路
想想可以使用什么数据结构
1、HashMap可以保存键和值(值存放次数),但是没有排序功能。我们还得全部取出遍历。
2、TreeSet可以排序但是只有单键
3、TreeMap 也不太行
4、可以使用小根堆(优先级队列)试试
其实,其本质是TopK问题,针对TopK问题,使用优先级队列是比较好用的。
优先级队列:https://blog.csdn.net/BillieFan/article/details/107578057
所谓优先级队列,就是为了找到最值而产生的数据结构。
三、代码题解
package leetcode;
import java.util.*;
/*
* @author lzy
* @version 1.0
* */
public class topK {
public static void main(String[] args) {
int arr[] = {1,1,1,2,2,3};
int k = 2;
topK topK = new topK();
topK.topKFrequent(arr, k);
}
public int[] topKFrequent(int[] nums, int k) {
//想想可以使用什么数据结构
//1、HashMap可以保存键和值(值存放次数),但是没有排序功能。我们还得全部取出遍历。
//2、TreeSet可以排序但是只有单键
//3. TreeMap 也不太行
//4、可以使用小根堆试试
TreeMap<Integer,Integer> map = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
});
HashMap<Integer,Integer> map1 = new HashMap();
//k作为键 出现次数作为值
for (int item : nums) {
map1.put(item,map1.getOrDefault(item,0) + 1);
}
//使用小根堆
PriorityQueue<int[]> pq1 = new PriorityQueue<>((a, b) -> a[1] - b[1]);
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
PriorityQueue<int[]> queue1 = new PriorityQueue<int[]>(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
});
PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> a[1] - b[1]);
//遍历HashMap将其中存放的键值放入优先级队列,利用优先级队列的特点选出前K个元素
for (Map.Entry<Integer, Integer> item : map1.entrySet()) {
//将key 和 value 放入数组,然后再将数组放入优先级队列进行排序,排序的手段是根据数据的arr[1]来比较的,也就是出现次数
int arr[] = {item.getKey(), item.getValue()};
queue.offer(arr);
//我们只需要找到前k个出现次数最多的即可,所以我们使用小根堆,根头永远放的次数最少的,所以一旦根堆size大于K,我们只需要把根头删掉即可。
if (queue.size() > k) {
queue.poll();
}
}
int res[] = new int[k];
for (int i = k - 1; i >= 0; i--) {
//根堆中存放的元素是数组,我们只需要取出数组第1个元素即可。
res[i] = queue.poll()[0];
}
return res;
}
}
时间复杂度: nlogk
调整根堆的时间复杂度为树的高度 也就是logn
暴力解法:
用HashMao存key和出现次数,然后遍历 K次 HashMap ,依次找到 K 个最大的值。
public int[] topKFrequent(int[] nums, int k) {
if (nums == null) {
return new int[]{};
}
int length = nums.length;
int[] answer = new int[k];
HashMap<Integer, Integer> map = new HashMap<>(16);
for (int i = 0; i < length; i++) {
int num = nums[i];
map.put(num, map.getOrDefault(num, 0) + 1);
}
for (int i = 0; i < k; i++) {
int n = Integer.MIN_VALUE;
int count = 0;
for (Integer number : map.keySet()) {
if (map.get(number) > count) {
count = map.get(number);
n = number;
}
}
map.put(n, 0);
answer[i] = n;
}
return answer;
}