题目:
给一非空的单词列表,返回前 k 个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。
示例:
解题思路:
先不考虑复杂度,这个题涉及到字符串排序,首先想到大根堆小根堆以及hashmap。大根堆小根堆还不熟,先考虑hashmap,想法是key,value(String,Integer),每重复一个加1,先设默认值,用hashmap.getOrDefault(String a,0)来设初始Integer为零。
第一步遍历完之后,时间复杂度为O(N),空间复杂度最坏情况(没有重复项)为为O(N)
第二步用一个list来存hashmap里面的key,直接用hashmap.keySet()初始化到ArrayList数组里即可。
第三步对数组进行自定义的排序,需要重写compare方法,这个之前没遇到过,需要牢记。
由于是最大排序,首先看hashmap里面该字符出现的次数,谁最大放前面,所以返回的是b.count-a.count。但是当次数相同时,按照谁小(字母表在前面)谁在前面,则返回a.compareTo(b),具体看一下代码。
参考:
爱情不够甜692.前K个高频单词
Java代码:
public class Solution {
public List<String> topKFrequent(String[] words, int k) {
// 1.初始化 哈希表 key -> 字符串 value -> 出现的次数。
Map<String, Integer> count = new HashMap<>();
for (String word : words) {
count.put(word, count.getOrDefault(word, 0) + 1);
}
// 2.用 list 存储字符 key 然后自定义 Comparator 比较器对 value 进行排序。
List<String> candidates = new ArrayList<>(count.keySet());
//这里是常规写法
// list.sort(new Comparator<String>(){
// @Override
// public int compare(String a,String b){
// if(map.get(a)==map.get(b)){
// return a.compareTo(b);
// }else{
// return map.get(b)-map.get(a);
// }
// }
// });
// 此处为使用 lambda 写法
candidates.sort((a, b) -> {
// 字符串频率相等按照字典序比较使得大的在堆顶,Java 可以直接使用 compareTo 方法即可。
if (count.get(a).equals(count.get(b))) {
return a.compareTo(b);
} else {
// 字符串频率不等则按照频率排列。
return count.get(b) - count.get(a);
}
});
// 3.截取前 K 大个高频单词返回结果。
return candidates.subList(0, k);
}
}
复杂度分析:
时间复杂度是前期遍历O(n),排序O(nlogn)最终就是O(NlogN),空间复杂度O(N),需要能存储N个字符串的hashmap和数组。