zoukankan      html  css  js  c++  java
  • [LeetCode] 347. Top K Frequent Elements

    Given a non-empty array of integers, return the k most frequent elements.

    Example 1:

    Input: nums = [1,1,1,2,2,3], k = 2
    Output: [1,2]
    

    Example 2:

    Input: nums = [1], k = 1
    Output: [1]

    Note:

    • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
    • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
    • It's guaranteed that the answer is unique, in other words the set of the top k frequent elements is unique.
    • You can return the answer in any order.

    前K个高频元素。题意是给一个非空数组,请返回前K个高频元素。前K个XX的题型思路大多不是pq就是bucket sort。题目要求时间复杂度必须优于O(nlogn)

    因为题目有时间复杂度的要求所以只能是bucket sort桶排序的思想做。这题Java的时间复杂度稍稍优于JS,是因为实现方式的不同导致。

    Java时间O(n),JS时间O(nlogn)

    空间O(n)

    解释一下思路,既然是桶排序,所以需要将出现频率一样的元素放到同一个桶里面,所以这里会用到一个hashmap记录数字和他们各自出现频率(key:value)。接着就需要根据频率大小,挑出前K个频率最大的元素。在JS里面,map是可以根据value排序的(21行),排序完之后,可以根据排序结果,再反过来挑出前K个key(24行)。因为21行用到了快排quick sort,所以时间复杂度至少为O(nlogn)

    JavaScript实现

     1 /**
     2  * @param {number[]} nums
     3  * @param {number} k
     4  * @return {number[]}
     5  */
     6 var topKFrequent = function (nums, k) {
     7     // corner case
     8     if (!nums || !nums.length) {
     9         return [];
    10     };
    11 
    12     // normal case
    13     let map = new Map();
    14     nums.forEach((item) => {
    15         if (map.has(item)) {
    16             map.set(item, map.get(item) + 1);
    17         } else {
    18             map.set(item, 1);
    19         }
    20     })
    21     let res = [...map].sort((a, b) => b[1] - a[1]);
    22     console.log(res);
    23     res = res.map(item => item[0]);
    24     return res.slice(0, k);
    25 };

    Java实现

    在Java里面这一题的实现方式略有不同。依然是需要创建一个hashmap记录元素和其频率(第9行)。之后创建桶需要用到一个list,每一个index上连着一个linkedlist,记录同样频率的元素都有哪些(12行)。因为桶排序的桶是按照频率有序排列的,所以最后输出结果的时候可以按桶频率由大到小依次将桶内元素加入结果集(20行)。

     1 class Solution {
     2     public List<Integer> topKFrequent(int[] nums, int k) {
     3         HashMap<Integer, Integer> map = new HashMap<>();
     4         for (int num : nums) {
     5             map.put(num, map.getOrDefault(num, 0) + 1);
     6         }
     7 
     8         List<Integer>[] bucket = new List[nums.length + 1];
     9         for (int num : map.keySet()) {
    10             int freq = map.get(num);
    11             if (bucket[freq] == null) {
    12                 bucket[freq] = new LinkedList<>();
    13             }
    14             bucket[freq].add(num);
    15         }
    16 
    17         List<Integer> res = new ArrayList<>();
    18         for (int i = bucket.length - 1; i >= 0 && res.size() < k; i--) {
    19             if (bucket[i] != null) {
    20                 res.addAll(bucket[i]);
    21             }
    22         }
    23         return res;
    24     }
    25 }

    Java, new code signature updated in June 2020.

     1 class Solution {
     2     public int[] topKFrequent(int[] nums, int k) {
     3         HashMap<Integer, Integer> map = new HashMap<>();
     4         for (int num : nums) {
     5             map.put(num, map.getOrDefault(num, 0) + 1);
     6         }
     7 
     8         List<Integer>[] bucket = new List[nums.length + 1];
     9         for (int num : map.keySet()) {
    10             int freq = map.get(num);
    11             if (bucket[freq] == null) {
    12                 bucket[freq] = new LinkedList<>();
    13             }
    14             bucket[freq].add(num);
    15         }
    16 
    17         int[] res = new int[k];
    18         int cur = 0;
    19         for (int i = bucket.length - 1; i > 0; i--) {
    20             if (bucket[i] == null) {
    21                 continue;
    22             }
    23             for (int n : bucket[i]) {
    24                 res[cur] = n;
    25                 cur++;
    26                 if (cur == k) {
    27                     return res;
    28                 }
    29             }
    30         }
    31         return res;
    32     }
    33 }

    Java Priority Queue 实现 - 时间复杂度O(nlogn)

     1 class Solution {
     2     public int[] topKFrequent(int[] nums, int k) {
     3         HashMap<Integer, Integer> map = new HashMap<>();
     4         for (int num : nums) {
     5             map.put(num, map.getOrDefault(num, 0) + 1);
     6         }
     7 
     8         PriorityQueue<Map.Entry<Integer, Integer>> maxHeap = new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());
     9         for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    10             maxHeap.offer(entry);
    11         }
    12         int[] res = new int[k];
    13         for (int i = 0; i < k; i++) {
    14             res[i] = maxHeap.poll().getKey();
    15         }
    16         return res;
    17     }
    18 }

    LeetCode 题目总结

  • 相关阅读:
    oracle-RAC修改服务器ip
    windows下安装sphinx-3.1.1
    linux下安装sphinx-for-chinese 支持中文全文索引
    TP通过sphinxapi接口实现全文搜索
    oracle常用公式
    查看TR请求内所有对象信息
    请求释放后如何取消释放
    S4 TO HANA 升级 比对升级过程中的程序变更 TR
    S4,执行外币评估(FAGL_FCV)后,对原因代码的替代不生效
    OVAH 由原提示消息改成报错 SO
  • 原文地址:https://www.cnblogs.com/cnoodle/p/12440505.html
Copyright © 2011-2022 走看看