Skip to content

Commit a8e5048

Browse files
author
luzhipeng
committed
2 parents f986c26 + d02913c commit a8e5048

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

Diff for: daily/2019-06-08.md

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
## 每日一题 - Top K Frequent Elements
2+
3+
### 信息卡片
4+
5+
- 时间:2019-06-08
6+
- 题目链接:https://leetcode.com/problems/top-k-frequent-elements/description/
7+
- tag:`Hash Table` `Heap`
8+
9+
### 题目描述
10+
11+
```
12+
Given a non-empty array of integers, return the k most frequent elements.
13+
14+
Example 1:
15+
16+
Input: nums = [1,1,1,2,2,3], k = 2
17+
Output: [1,2]
18+
19+
Example 2:
20+
21+
22+
Input: nums = [1], k = 1
23+
Output: [1]
24+
25+
Note:
26+
27+
You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
28+
Your algorithm's time complexity must be better than O(n log n), where n is
29+
the array's size.
30+
```
31+
32+
简单来说,此题要求找出一个数组中出现次数最多的前K个数。
33+
34+
### 参考答案
35+
36+
以下参考答案均是以Java语言实现,不过对其他语言,思路都是相同的。
37+
38+
题目要求时间复杂度必须比O(n log n)要好,第一种解法的复杂度是O(n),第二种解法由于使用了优先队列,时间复杂度要比O(n)略差,但仍然能AC,所以优先推荐第一种使用HashMap + 桶的解法。
39+
40+
#### 解法I:HashMap + 桶
41+
42+
* 用HashMap统计所有元素的出现频率
43+
* 将统计结果按照出现次数把对应元素放入以出现次数为基础的桶中
44+
* 按照从后往前的顺序从桶中取前K个元素便是答案
45+
46+
参考代码
47+
```java
48+
class Solution {
49+
public List<Integer> topKFrequent(int[] nums, int k) {
50+
if (nums == null || nums.length == 0 || k <= 0) return Collections.emptyList();
51+
52+
Map<Integer, Integer> statisticMap = new HashMap<>();
53+
54+
for (int i : nums) statisticMap.put(i, statisticMap.getOrDefault(i, 0) + 1);
55+
56+
// 记录出现次数和对应元素的桶
57+
List<Integer>[] bucket = new List[nums.length + 1];
58+
59+
for (int i : statisticMap.keySet()) {
60+
int frequency = statisticMap.get(i);
61+
62+
if (bucket[frequency] == null) bucket[frequency] = new ArrayList<Integer>();
63+
64+
bucket[frequency].add(i);
65+
}
66+
67+
List<Integer> result = new ArrayList<>();
68+
69+
for (int i = bucket.length - 1; i >= 0; i--) {
70+
if (bucket[i] == null) continue;
71+
72+
if (result.size() >= k) break;
73+
74+
result.addAll(bucket[i]);
75+
}
76+
77+
return result;
78+
}
79+
}
80+
```
81+
#### 解法II:HashMap + PriorityQueue
82+
83+
思路大致和前面相同,不过是将出现频率的排序交给了优先队列而已,在使用优先队列的时候给其提供了一个比较器,该比较器会对加入的元素自动排序,最后选择优先队列的前K的元素返回即可。
84+
85+
参考代码
86+
```java
87+
class Solution {
88+
public List<Integer> topKFrequent(int[] nums, int k) {
89+
if (nums == null || nums.length == 0 || k <= 0) return Collections.emptyList();
90+
91+
Map<Integer, Integer> map = new HashMap<>();
92+
93+
for (int i : nums) map.put(i, map.getOrDefault(i, 0) + 1);
94+
95+
// 优先队列
96+
PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
97+
@Override
98+
public int compare(Map.Entry<Integer, Integer> e1, Map.Entry<Integer, Integer> e2) {
99+
return e2.getValue() - e1.getValue(); // 确保出现次数多的数排列在队列的前面
100+
}
101+
});
102+
103+
for (Map.Entry<Integer, Integer> entry : map.entrySet()) pq.add(entry);
104+
105+
int i = 1;
106+
List<Integer> result = new ArrayList<>();
107+
108+
while (i++ <= k) result.add(pq.poll().getKey());
109+
110+
return result;
111+
}
112+
}
113+
```
114+
### 其他优秀解答
115+
116+
本题基本上好的解答就是上面的两种办法,为了格式和其他同学的PR尽量一致,我在编写此PR的时候删去了我解题时写下的详细注释,需要看详细注释的同学请[移步此处的第347题](https://github.com/jsycdut/leetcode/tree/master/practice/leetcode/301-400)

Diff for: daily/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ tag: `Array`
2323

2424
时间: 2019-06-05
2525

26+
#### [347.Top K Frequent Elements](./2019-06-08.md)
27+
28+
tag: `HashTable Heap`
29+
30+
时间: 2019-06-08
31+
2632
#### [617. Merge Two Binary Trees](./2019-06-10.md)
2733

2834
tag: `Tree`

0 commit comments

Comments
 (0)