LeetCode(top100)前k个高频元素

前k个高频元素

题目描述

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

题目分析

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
输入: nums = [1], k = 1
输出: [1]
提示:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案。

思路(一)

map和数组排序方法

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    //[...new Set(array)] 一种数组去重方法
    let arr = [...new Set(nums)]     //nums=[1,1,1,2,2,3] arr=[1,2,3]
   //统计数组中每个元素出现的次数
    var map=new Map();
    for(let c of nums){
        if(map.has(c)){
            map.set(c,map.get(c)+1)
        }else{
            map.set(c,1);
        }
    }
    
     //根据数组中每个元素出现的次数大小对数组中的元素进行排序,取前k大
     return arr.sort((a, b) => map.get(b) - map.get(a)).slice(0, k);
};
思路(二)

桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。

首先使用 map 来存储频率
然后创建一个数组(有数量的桶),将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标(桶内)即可

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
   let map=new Map();     //使用map统计元素key和频率value
   for(let c of nums){
       if(map.has(c)){
           map.set(c,map.get(c)+1);
       }else{
           map.set(c,1);
       }
   }
    if(map.size <= k) {    //如果统计后的map小于k,直接将map中所有的元素返回
         return [...map.keys()]
     }
    return bucketSort(map,k);
   
};
    let bucketSort = (map, k) => {
         let arr = [], res = []
         map.forEach((value, key) => {
          // 利用映射关系(出现频率作为下标)将数据分配到各个桶中
            if(!arr[value]) {     //以map中的频率value为下标,将元素key,对应映射到arr数组中(相当于按频率大小将元素从小到大排序)
               arr[value] = [key]
             } else {
                 arr[value].push(key)
        }
    })

    for(let i=0;i<arr.length;i++){
        if(arr[i]){
            res.push(...arr[i]); //注意将arr[i]前面填上...arr[i]
        }        
    }
    return res.slice(res.length-k);

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值