題目描述:
給一非空的單詞列表,返回前 k 個出現次數最多的單詞。返回的答案應該按單詞出現頻率由高到低排序。如果不同的單詞有相同出現頻率,按字母順序排序。
分析:
首先需要輸出出現次數最多的前K個單詞====》這就需要對出現的所有單詞進行次數統計,所以Map是此處最佳的選擇,又因爲不需要對單詞排序,所以選擇HashMap,查詢效率跟高(O(1))
又因爲需要在次數相同的情況下按照字母次序進行排序===》可以得知這是一個TOP-K問題
TOP-K問題:
- 首先構造包含K個元素的堆
- 用剩餘的元素依次和堆頂比較,檢查是否需要插入。
- 如果需要前K個最大----》創建小堆
- 如果需要前K個最小----》創建大堆
優先級隊列注意點:
對於自定義類型:必須提供比較器(Comparator)或者在自定義類中重寫Comparable接口。
解題思路:
- 統計每個單詞出現的次數---》HashMap
- 需要將鍵值對存放在優先級隊列中,並且實現Comparable接口---》按照單詞出現的次數從高向低排---》此處應該構建一個小堆,每次替換堆頂最小的鍵值對,替換後重新進行向下調整,將堆調整爲小堆,,,依次進行--》最後的堆就是所有次數最多的單詞組成的小堆。
- 將最後的堆中元素存入list中
- 實現比較器
代碼:
//比較器
class CmpKV implements Comparator<Map.Entry<String,Integer>>
{
public int compare(Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2)
{
if(o2.getValue() > o1.getValue())//o1的次數大於o2
{
return 1;
}
if(o2.getValue() == o1.getValue() && o1.getKey().compareTo(o2.getKey())>0)//次數相等,字符串比較
{
return 1;
}
if(o2.getValue() == o1.getValue() && o1.getKey().compareTo(o2.getKey())==0)//次數相等,字符串比較
{
return 0;
}
return -1;
}
}
class Solution {
public List<String> topKFrequent(String[] words, int k) {
//統計每個單詞出現的次數---》map
Map<String,Integer> m=new HashMap<>();
for(int i=0;i<words.length;i++)
{
String s=words[i];
if(m.containsKey(s))//如果map中有,讓對於的value+1
{
m.put(s,m.get(s)+1);
}else{//如果沒有,往map中添加
m.put(s,1);
}
}
//需要將鍵值對存放在優先級隊列中,並且實現Comparable接口---》按照單詞出現的次數從高向低排---》此處應該構建一個小堆,每次替換堆頂最小的鍵值對,替換後重新進行向下調整,將堆調整爲小堆,,,依次進行--》最後的堆就是所有次數最多的單詞組成的小堆。
PriorityQueue<Map.Entry<String,Integer>> queue=new PriorityQueue<>(new CmpKV());
for(Map.Entry<String,Integer> e:m.entrySet())
{
queue.offer(e);
}
//將最後的堆中元素存入list中
List<String> lRet=new ArrayList<>(k);
for(int i=0;i<k;i++)
{
lRet.add(queue.poll().getKey());//將堆頂元素添加到list中並且將其從堆//頂刪除
}
return lRet;
}
}