347. 前 K 个高频元素

347. 前 K 个高频元素

leetcode 347. 前 K 个高频元素


题目:347. 前 K 个高频元素

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例2:

输入: nums = [1], k = 1
输出: [1]

说明:

  • 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
  • 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
  • 你可以按任意顺序返回答案。

方法一:sort排序

思路:使用HashMap + ArrayList + sort,根据出现频率排序,返回频率最大的k个元素

运行数据:执行用时:16 ms,内存消耗:42.7 MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// LeetCode指定调用方法
public int[] topKFrequent(int[] nums, int k) {

// 记录每个元素出现的频率
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i : nums) {
map.put(i, map.getOrDefault(i, 0) + 1);
}

// 使用sort方法排序
List<Map.Entry<Integer, Integer>> list = new ArrayList<Map.Entry<Integer,Integer>>(map.entrySet());
list.sort(new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Entry<Integer, Integer> o1,
Entry<Integer, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});

// 记录频率最大的k个元素
int[] result = new int[k];
for (int i = 0; i < k; i++) {
result[i] = list.get(i).getKey();
}

return result;
}

方法二:堆排序(大顶堆)

思路:使用PriorityQueue,维护大顶堆,返回k个堆顶元素

运行数据:执行用时:16 ms,内存消耗:42.4 MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// LeetCode指定调用方法
public int[] topKFrequent(int[] nums, int k) {

// 记录每个元素出现的频率
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i : nums) {
map.put(i, map.getOrDefault(i, 0) + 1);
}

// 优先队列
PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> (map.get(o2) - map.get(o1)));
queue.addAll(map.keySet());

// 记录k个堆顶元素
int[] result = new int[k];
for (int i = 0;!queue.isEmpty() && i < k; i++) {
result[i] = queue.poll();
}

return result;
}

方法三:桶排序

思路:桶排序,将出现频率相同的放到一个桶中

运行数据:执行用时:12 ms,内存消耗:42.5 MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// LeetCode指定调用方法
public int[] topKFrequent3(int[] nums, int k) {

// 记录每个元素出现的频率
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i : nums) {
map.put(i, map.getOrDefault(i, 0) + 1);
}

// 将每个元素放到对应的桶中
List<Integer>[] arr = new ArrayList[nums.length + 1];
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int value = entry.getValue();
if (arr[value] == null) {
arr[value] = new ArrayList<>();
}
arr[value].add(entry.getKey());
}

// 频率最大的k个元素
int[] result = new int[k];
int t = 0;
for (int i = arr.length - 1; t < k && i > 0; i--) {
if (arr[i] == null) continue;
for (int item : arr[i]) {
result[t++] = item;
if (t == k) break;
}
}

return result;
}

学习所得,资料、图片部分来源于网络,如有侵权,请联系本人删除。

才疏学浅,若有错误或不当之处,可批评指正,还请见谅!


Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×