查看: 2019| 回复: 2
跳转到指定楼层
上一主题 下一主题
收起左侧

[字符串] 692. Top K Frequent Words有点不太懂

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
class Solution {
    public List<String> topKFrequent(String[] words, int k) {
         List<String> result = new LinkedList<>();
        Map<String, Integer> map = new HashMap<>();
        for(int i=0; i<words.length; i++)
        {
            if(map.containsKey(words[i]))
                map.put(words[i], map.get(words[i])+1);
            else
                map.put(words[i], 1);
        }

        PriorityQueue<Map.Entry<String, Integer>> pq = new PriorityQueue<>
        (
            (a,b) -> a.getValue().equals(b.getValue()) ?
            b.getKey().compareTo(a.getKey()) :                                                                       
            Integer.compare(a.getValue(),b.getValue())
        );

        for(Map.Entry<String, Integer> entry: map.entrySet())
        {
            pq.offer(entry);
            if(pq.size()>k)
                pq.poll();
        }

        while(!pq.isEmpty())
            result.add(0, pq.poll().getKey());

        return result;
    }
}
在 PriorityQueue  comparator 里面为什么吧 b.getKey().compareTo(a.getKey()) 写成 a.getKey().compareTo(b.getKey()) 就不行了,comparator 到底是怎么排序的?


上一篇:Leetcode 315 Count of Smaller Numbers After Self 离散化
下一篇:高效学习八小时
全局:
你这个问题我不是特别懂,我感觉你懂comparator, 但是似乎又是在问到底comparator怎么排序。。

先说这个pq。 按题目来说, 是要频率高的朝前拍, 如果频率一样高, 那就按字典序排。但是这个人写的是一个min pq, 所以是先按频率低的出, 如果频率一样, 就出字典序大的单词。

这也就是为什么他这里写成  (a,b) -> a.getValue().equals(b.getValue()) ? b.getKey().compareTo(a.getKey()) : Integer.compare(a.getValue(),b.getValue()) | 解读: [a, b] 相比, 频率一样吗? 字典序大的先 : 频率低的先

所以每次min pq 里面的空间大于K时, 就poll。

再来回答你的问题, Comparator 到底怎么排序的?

其实说难不难, 这都要怪1.8里面出了一个lambda expression, 对于1.8以前的人, 这段代码都得乖乖写成一个Comparator (anonymous)class

正经写的话, 应该是在外面加一个

```
class CompareByFreqThenLexi implements Comparator<Map.Entry<String, Integer>>
{
        public int compare(Map<String, Integer> o1, Map<String, Integer> o2)
        {
                int v1 = o1.getValue(), v2 = o2.getValue();
                if(v1 == v2)
                {
                        String s1 = o1.getKey(), s2 = o2.getKey();
                        return s2.compareTo(s1);
                }
                return v1 - v2;
        }
}
```

或者是像他这段, 只不过不是lambda expression, 而是加一个anonymous class
```
    PriorityQueue<Map.Entry<String, Integer>> pq = new PriorityQueue<>(new Comparator<Map<String, Integer>>()
    {
        public int compare(Map<String, Integer> o1, Map<String, Integer> o2)
        {
                int v1 = o1.getValue(), v2 = o2.getValue();
                if(v1 == v2)
                {
                        String s1 = o1.getKey(), s2 = o2.getKey();
                        return s2.compareTo(s1);
                }
                return v1 - v2;
        }
    });
```

现在是1.8时代了, 当然可以用lambda expression, 也就是你的例子中的这个。

不过我个人建议是, 如果你不太熟悉。。还是写comparator class。 或者这个写出来不是一句话, 就还是别这样折腾自己了。

送你一段这个题我写的[不太长的]方法。

```
    public List<String> topKFrequent(String[] words, int k) {
        Map<String, Integer> map = new HashMap<>();
        for(String word : words) map.put(word, map.getOrDefault(word, 0) + 1);
        List<String> list = new ArrayList<>(map.keySet());
        Collections.sort(list, (a, b) -> (map.get(b) == map.get(a) ? a.compareTo(b) : map.get(b) - map.get(a)));
        return list.subList(0, k);
    }
```

其实意思都一样了o( ̄ヘ ̄o#)


补充内容 (2018-7-11 11:30):
如果你comparator class不太懂的话, 上网找点材料或者视频学习一下就好了, 挺容易理解的。

评分

参与人数 1大米 +1 收起 理由
guojin + 1 很有用的信息!

查看全部评分

回复

使用道具 举报

🔗
monsoonle 2018-7-12 01:26:08 | 只看该作者
全局:
comparator 默认是最小堆
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表