[LeetCode] 692. Top K Frequent Words

 

Given an array of strings words and an integer k, return the k most frequent strings.

Return the answer sorted by the frequency from highest to lowest. Sort the words with the same frequency by their lexicographical order.

Example 1:

Input: words = ["i","love","leetcode","i","love","coding"], k = 2
Output: ["i","love"]
Explanation: "i" and "love" are the two most frequent words.
Note that "i" comes before "love" due to a lower alphabetical order.

Example 2:

Input: words = ["the","day","is","sunny","the","the","the","sunny","is","is"], k = 4
Output: ["the","is","sunny","day"]
Explanation: "the", "is", "sunny" and "day" are the four most frequent words, with the number of occurrence being 4, 3, 2 and 1 respectively.

Constraints:

  • 1 <= words.length <= 500
  • 1 <= words[i].length <= 10
  • words[i] consists of lowercase English letters.
  • k is in the range [1, The number of unique words[i]]

Follow-up: Could you solve it in O(n log(k)) time and O(n) extra space?

前K个高频单词。

给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/top-k-frequent-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

因为是前 K 个 XX 的题型所以思路不是优先队列就是 bucket sort。本题是用到 heap/priority queue。先用 hashmap 存每个单词和他们出现的频率,然后用 pq 创建一个最小堆,并且做一个 comparator 比较 map 的entrySet,如果 map 中两个 key 的 value 相同,则比较这两个 key 的字母排序,字典序小的在前,否则就按照这两个 key 对应的 value 大小排序。最后用一个 linkedlist 输出结果,注意将单词加入 res 的时候要加在 list 的头部,因为从 pq 弹出的元素是最小的,所以最后一个弹出的元素应该排在 list 的最前面。

二刷的时候想不起来为什么一定要用最小堆。其实用最大堆也行,但是最小堆可以在创建的时候直接定义 size K,当堆的 size 到达 K 的时候,之后再放进来的元素如果更大,会把堆顶元素挤掉;如果再放进来的元素更小,则无法放进堆。这个操作会节省一点时间。

时间O(nlogk)

空间O(n)

Java实现最小堆

 1 class Solution {
 2     public List<String> topKFrequent(String[] words, int k) {
 3         List<String> res = new ArrayList<>();
 4         HashMap<String, Integer> map = new HashMap<>();
 5         for (String word : words) {
 6             map.put(word, map.getOrDefault(word, 0) + 1);
 7         }
 8         
 9         // 如果两个key的value相同,则字典序小的在堆顶
10         // 否则把value大的key放在堆顶
11         PriorityQueue<Map.Entry<String, Integer>> queue = new PriorityQueue<>((a, b) -> a.getValue() == b.getValue() ? a.getKey().compareTo(b.getKey()) : b.getValue() - a.getValue());
12         for (Map.Entry<String, Integer> entry : map.entrySet()) {
13             queue.offer(entry);
14         }
15         
16         for (int i = 0; i < k; i++) {
17             res.add(queue.poll().getKey());
18         }
19         return res;
20     }
21 }

 

时间O(nlogk)

空间O(n)

Java实现最大堆

 1 class Solution {
 2     public List<String> topKFrequent(String[] words, int k) {
 3         HashMap<String, Integer> map = new HashMap<>();
 4         for (String s : words) {
 5             map.put(s, map.getOrDefault(s, 0) + 1);
 6         }
 7         PriorityQueue<Map.Entry<String, Integer>> maxHeap = new PriorityQueue<>(k, (a,
 8                 b) -> a.getValue() == b.getValue() ? a.getKey().compareTo(b.getKey()) : b.getValue() - a.getValue());
 9         for (Map.Entry<String, Integer> entry : map.entrySet()) {
10             maxHeap.offer(entry);
11         }
12         List<String> res = new ArrayList<>();
13         while (res.size() < k) {
14             res.add(maxHeap.poll().getKey());
15         }
16         return res;
17     }
18 }

 

LeetCode 题目总结

posted @ 2020-03-13 14:50  CNoodle  阅读(239)  评论(0编辑  收藏  举报