2023-2-7 前K个高频单词 【哈希+最小堆】

题目:

给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序排序。

思路:
1,Hash提取字符频次
2,构建最小堆,然后动态的添加、删除队列首元素直至最后的堆的数据

3,将堆中的数据取出,然后反转一下就行

代码如下:

 public  static List<String> topKFrequent(String[] words, int k) {
  // 1 利用哈希提取频次
        HashMap<String, Integer> map = new HashMap();
        for(String str:words){
            map.put(str,map.getOrDefault(str,0)+1);
        }

        //  建小堆
        PriorityQueue<String> queue = new PriorityQueue((a,b)->{
            if(map.get(a).equals(map.get(b))){
               // 如果频次一样,则还需要按照字典顺序排序
               // 注意,这里的b、a顺序不能搞反,原因在于在堆内中、频次相同的,按照字典顺序靠前优先排序,字典值靠前意味着ASCLL码越小
               // 而compareTo函数比较的就是ASCLL码,a.compareTo(b):表示升序,b.compareTo(a):表示降序
                return  ((String)b).compareTo((String)a);
            }else{
                return  map.get(a) - map.get(b);
            }
        });

        // 将数据放入堆中
        for(String str: map.keySet() ){
            if(queue.size()<k){
                queue.offer(str);
                continue;
            }

            // 堆满K个元素之后,后续加入的节点频次必须高于或者等于队列首元素的频次
            // 考虑到频次相等的时还需要按字典顺序排序的情况(注意,这个选择字典靠前的(ASCLL码较小的))
            if(map.get(queue.peek())<=map.get(str)){
                if(map.get(queue.peek())==map.get(str)){
                    if(str.compareTo(queue.peek())<0) {
                        queue.poll();
                        queue.offer(str);
                    }
                   continue;
                }
                queue.poll();
                queue.offer(str);
            }
        }

        List<String> strList = new ArrayList<>();
        while(!queue.isEmpty()){
            strList.add(queue.poll());
        }

        Collections.reverse(strList);
        return strList;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值