【Lintcode】471. Top K Frequent Words

题目地址:

https://www.lintcode.com/problem/top-k-frequent-words/description

给定一个单词的数组,问其出现频率最高的 k k k个单词是哪些。如果有出现频率相同的单词,则认为字典序小的那个入选。

思路是用小顶堆。因为我们需要选出现频率最高并且字典序小的单词,所以我们构造小顶堆的时候,就让出现频率低和字典序大的单词优先级更高。注意,这里要先对 k = 0 k=0 k=0的情况进行判断。代码如下:

import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class Solution {
    /**
     * @param words: an array of string
     * @param k: An integer
     * @return: an array of string
     */
    public String[] topKFrequentWords(String[] words, int k) {
        // write your code here
        // 如果k = 0则返回空数组
        if (k == 0) {
            return new String[0];
        }
        // 先用一个哈希表统计每个单词的出现频率
        Map<String, Integer> freq = new HashMap<>();
        for (String word : words) {
            freq.put(word, freq.getOrDefault(word, 0) + 1);
        }
        // 构造一个小顶堆,单词出现频率小的优先,如果频率一样,则字典序大的优先
        PriorityQueue<String> minHeap = new PriorityQueue<>((s1, s2) -> {
            if (!freq.get(s1).equals(freq.get(s2))) {
                return freq.get(s1) < freq.get(s2) ? -1 : 1;
            } else {
                for (int i = 0, j = 0; i < s1.length() && j < s2.length(); i++, j++) {
                    if (s1.charAt(i) != s2.charAt(j)) {
                        return s1.charAt(i) > s2.charAt(j) ? -1 : 1;
                    }
                }
                
                return s1.length() > s2.length() ? -1 : 1;
            }
        });
        
        // 如果发现新来的单词频率比堆顶更高,或者虽然频率一样但字典序靠前,则将堆顶踢出堆,将新来的词加入堆
        for (String word : freq.keySet()) {
            if (minHeap.size() < k) {
                minHeap.offer(word);
            } else {
                if (freq.get(word) > freq.get(minHeap.peek()) ||
                        (freq.get(word).equals(freq.get(minHeap.peek())) && word.charAt(0) < minHeap.peek().charAt(0))) {
                    minHeap.poll();
                    minHeap.offer(word);
                }
            }
        }
        // 逆序对res赋值
        String[] res = new String[k];
        for (int i = k - 1; i >= 0; i--) {
            res[i] = minHeap.poll();
        }
        
        return res;
    }
}

时间复杂度 O ( n l log ⁡ k ) O(nl\log k) O(nllogk),空间 O ( n l ) O(nl) O(nl) n n n为单词个数, l l l为最长单词长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值