692.前K个高频单词(中等)|Java刷题打卡

362 阅读2分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接

题目

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/to…

给一非空的单词列表,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。

示例 1:

输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2 输出: ["i", "love"] 解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。 注意,按字母顺序 "i" 在 "love" 之前。

示例 2:

**输入: **["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4 输出: ["the", "is", "sunny", "day"] 解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词, 出现次数依次为 4, 3, 2 和 1 次。

注意:

  1. 假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。
  2. 输入的单词均由小写字母组成。

扩展练习:

尝试以O(n log k)时间复杂度和O(n)空间复杂度解决。

问题分析

这道题意思很明确了,根据单词出现的次数排序,次数相同的看字母顺序,最后取前k

遍历数组,将单词及单词出现次数放在Map中,把Map根据value排序,value相同的根据字母排序,最后取前k个key值就可以了,思路也非常清晰

public class Solution {

  public List<String> topKFrequent(String[] words, int k) {
    return Arrays.stream(words)
        .collect(Collectors.groupingBy(String::toString, TreeMap::new, Collectors.counting()))
        .entrySet().stream()
        .sorted(
            Entry.<String, Long>comparingByValue().reversed().
        ).map(Entry::getKey).collect(Collectors.toList()).subList(0, k);
  }
}

总结

如果用lambda表达式来写,一行代码就可以解决问题,这种不一定符合算法题的解题要求,但是平时写代码的时候会经常用到这些东西

  • groupingBy的作用是分组,它返回的是一个map。groupingby可以有三个参数,第一个表示要分组的字段,是返回结果的key,第二个表示返回结果的类型,第三个是返回结果的value值
  • collet可以将stream再次转化为集合类
  • Entry.<String, Long>comparingByValue()表示将map根据value值排序,map根据key值排序的话用Entry.<String, Long>comparingByKey()
  • reversed表示反序,原来是从小到大,变成从大到小
  • map可以对集合类进行转化,或者说对集合中的元素进行操作