forked from azl397985856/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/azl397985856/leetcode
- Loading branch information
Showing
2 changed files
with
122 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
## 每日一题 - Top K Frequent Elements | ||
|
||
### 信息卡片 | ||
|
||
- 时间:2019-06-08 | ||
- 题目链接:https://leetcode.com/problems/top-k-frequent-elements/description/ | ||
- tag:`Hash Table` `Heap` | ||
|
||
### 题目描述 | ||
|
||
``` | ||
Given a non-empty array of integers, return the k most frequent elements. | ||
Example 1: | ||
Input: nums = [1,1,1,2,2,3], k = 2 | ||
Output: [1,2] | ||
Example 2: | ||
Input: nums = [1], k = 1 | ||
Output: [1] | ||
Note: | ||
You may assume k is always valid, 1 ≤ k ≤ number of unique elements. | ||
Your algorithm's time complexity must be better than O(n log n), where n is | ||
the array's size. | ||
``` | ||
|
||
简单来说,此题要求找出一个数组中出现次数最多的前K个数。 | ||
|
||
### 参考答案 | ||
|
||
以下参考答案均是以Java语言实现,不过对其他语言,思路都是相同的。 | ||
|
||
题目要求时间复杂度必须比O(n log n)要好,第一种解法的复杂度是O(n),第二种解法由于使用了优先队列,时间复杂度要比O(n)略差,但仍然能AC,所以优先推荐第一种使用HashMap + 桶的解法。 | ||
|
||
#### 解法I:HashMap + 桶 | ||
|
||
* 用HashMap统计所有元素的出现频率 | ||
* 将统计结果按照出现次数把对应元素放入以出现次数为基础的桶中 | ||
* 按照从后往前的顺序从桶中取前K个元素便是答案 | ||
|
||
参考代码 | ||
```java | ||
class Solution { | ||
public List<Integer> topKFrequent(int[] nums, int k) { | ||
if (nums == null || nums.length == 0 || k <= 0) return Collections.emptyList(); | ||
|
||
Map<Integer, Integer> statisticMap = new HashMap<>(); | ||
|
||
for (int i : nums) statisticMap.put(i, statisticMap.getOrDefault(i, 0) + 1); | ||
|
||
// 记录出现次数和对应元素的桶 | ||
List<Integer>[] bucket = new List[nums.length + 1]; | ||
|
||
for (int i : statisticMap.keySet()) { | ||
int frequency = statisticMap.get(i); | ||
|
||
if (bucket[frequency] == null) bucket[frequency] = new ArrayList<Integer>(); | ||
|
||
bucket[frequency].add(i); | ||
} | ||
|
||
List<Integer> result = new ArrayList<>(); | ||
|
||
for (int i = bucket.length - 1; i >= 0; i--) { | ||
if (bucket[i] == null) continue; | ||
|
||
if (result.size() >= k) break; | ||
|
||
result.addAll(bucket[i]); | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
``` | ||
#### 解法II:HashMap + PriorityQueue | ||
|
||
思路大致和前面相同,不过是将出现频率的排序交给了优先队列而已,在使用优先队列的时候给其提供了一个比较器,该比较器会对加入的元素自动排序,最后选择优先队列的前K的元素返回即可。 | ||
|
||
参考代码 | ||
```java | ||
class Solution { | ||
public List<Integer> topKFrequent(int[] nums, int k) { | ||
if (nums == null || nums.length == 0 || k <= 0) return Collections.emptyList(); | ||
|
||
Map<Integer, Integer> map = new HashMap<>(); | ||
|
||
for (int i : nums) map.put(i, map.getOrDefault(i, 0) + 1); | ||
|
||
// 优先队列 | ||
PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() { | ||
@Override | ||
public int compare(Map.Entry<Integer, Integer> e1, Map.Entry<Integer, Integer> e2) { | ||
return e2.getValue() - e1.getValue(); // 确保出现次数多的数排列在队列的前面 | ||
} | ||
}); | ||
|
||
for (Map.Entry<Integer, Integer> entry : map.entrySet()) pq.add(entry); | ||
|
||
int i = 1; | ||
List<Integer> result = new ArrayList<>(); | ||
|
||
while (i++ <= k) result.add(pq.poll().getKey()); | ||
|
||
return result; | ||
} | ||
} | ||
``` | ||
### 其他优秀解答 | ||
|
||
本题基本上好的解答就是上面的两种办法,为了格式和其他同学的PR尽量一致,我在编写此PR的时候删去了我解题时写下的详细注释,需要看详细注释的同学请[移步此处的第347题](https://github.com/jsycdut/leetcode/tree/master/practice/leetcode/301-400) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters