【堆】B006_前 K 个高频单词(排序 | maxHeap| minHeap)

一、题目描述

Given a non-empty list of words, return the k most frequent elements.

Your answer should be sorted by frequency from highest to lowest. 
If two words have the same frequency, 
then the word with the lower alphabetical order comes first.

Input: ["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.

二、题解

方法一:大根堆

思路

  • 首先记录每个单词出现的频次。
  • 创建优先队列构建大根堆,根据题目排序规则定义 Comparator。
    • 先按单词的频次降序排列;频次相同,则按字母表降序排列。
  • 将 Map 中的 key 值,全加到 pq 中。
  • 最后取出优先队列前 k 个元素即为结果。
/**
 * @date: 2/21/2020 11:11 AM
 * @Execution info:8ms,97%,MB,5.08%
 */
public List<String> topKFrequent(String[] words, int k) {

  HashMap<String, Integer> map = new HashMap<>();
  for (String word : words) {
    map.put(word, map.getOrDefault(word, 0) + 1);
  }

  PriorityQueue<String> pQ = new PriorityQueue<>(new Comparator<String>() {
    @Override
    public int compare(String word1, String word2) {
      if (map.get(word1) - map.get(word2) == 0) {     //频次相同,则按字母表顺序排列
        return word1.compareTo(word2);
      }
      return map.get(word2).compareTo(map.get(word1));//按照出现频率从大到小排序
    }
  });

  for (String word : map.keySet()) {
    pQ.add(word);
  }
  LinkedList<String> retList = new LinkedList<>();
  while (k-- > 0) {
    retList.add(pQ.poll());
  }
  return retList;
}

复杂度分析

  • 时间复杂度:O(N logN),建立映射需要 o(N) 时间,建堆需要 N log N 时间。
  • 空间复杂度:O(2N),N 为单词的种类。

方法二:最小堆(优化)

思路

  • 始终维护小根堆的大小为 k 。
  • 队列会将频率最小的单词放在队头,出现频次比队头大的将队头单词出队。
  • 最后,队列中的 k 个单词就是逆序的前k 个高频单词。
/**
   * @date: 2/21/2020 11:14 AM
   * @Execution info:ms,%,%
   */
  public List<String> topKFrequent1(String[] words, int k) {
    LinkedList<String> retList = new LinkedList<>();
    HashMap<String, Integer> map = new HashMap<>();
    for (String word : words) {
      map.put(word, map.getOrDefault(word, 0) + 1);
    }

    PriorityQueue<String> pQ = new PriorityQueue<>(new Comparator<String>() {
      @Override
      public int compare(String word1, String word2) {
        if (map.get(word1) - map.get(word2) == 0) {     //频次相同,则按字母表顺序排列
          return word2.compareTo(word1);
        }
        return map.get(word1).compareTo(map.get(word2));//按照出现频率从小到大排序
      }
    });

    for (String word : map.keySet()) {
      pQ.add(word);
      if (pQ.size() > k)
        pQ.poll();
    }
    
//    while (!pQ.isEmpty()) {
//      retList.addFirst(pQ.poll());
//    }
    while (!pQ.isEmpty()) {
      retList.add(pQ.poll());
    }
    Collections.reverse(retList);
    return retList;
  }

复杂度分析

  • 时间复杂度: O(N log k),建立映射需要 O(n),建堆需要 O(N logk)
  • 空间复杂度: O(N + k),k 总是小于等于 N。
发布了419 篇原创文章 · 获赞 94 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/104424657