[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 }