(1)使用map记录字符的出现次数;

(2)使用小根堆保存前k的结果(满足要求时间复杂度nlogk的要求);

注意:定义堆的比较器,除了要考虑字符串出现次数值的大小,当出现次数相同时,还要比较字符串的字典序



public class Solution {
    /**
     * return topK string
     * @param strings string字符串一维数组 strings
     * @param k int整型 the k
     * @return string字符串二维数组
     */
    public String[][] topKstrings (String[] strings, int k) {
        String[][] res = new String[k][2];
        //记录字符出现次数
        HashMap<String,Integer> map = new HashMap<>();
        for(int i = 0; i < strings.length; i++){
            if(map.containsKey(strings[i])){
                map.put(strings[i], map.get(strings[i]) + 1);
            }else{
                map.put(strings[i], 1);
            }
        }
        //建立小根堆,自定义比较器(次数值value相同,比较key的字典序,不相同直接比较次数值value)
        PriorityQueue<Map.Entry<String,Integer>> pq = new PriorityQueue<>((o1,o2) -> o1.getValue().equals(o2.getValue()) ? o2.getKey().compareTo(o1.getKey()) : o1.getValue()-o2.getValue());
        int size = 0;
        //维护size为k的小根堆
        for(Map.Entry<String,Integer> m : map.entrySet()){
            if(size < k){
                pq.offer(m);
                size++;
            }
            //大于堆顶元素插入
            else if((m.getValue().equals(pq.peek().getValue()) ? pq.peek().getKey().compareTo(m.getKey()) : m.getValue() - pq.peek().getValue()) > 0){
                pq.poll();
                pq.offer(m);
            }
        }
        //取出堆中元素,从后向前放置
        for(int i = k - 1; i >= 0; i--){
            Map.Entry<String,Integer> entry =(Map.Entry)pq.poll();
            res[i][0] = entry.getKey();
            res[i][1] = String.valueOf(entry.getValue());
        }
        return res;
    }
}