手摸手提桶跑路——LeetCode347.前k个高频元素

175 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

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

示例 2:

输入: nums = [1], k = 1
输出: [1]

提示:

  • 1 <= nums.length <= 105
  • k 的取值范围是 [1, 数组中不相同的元素的个数]
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的  

解题思路——桶排序

桶排序需要先知道桶的大小,也就是说第一遍遍历数组需要统计出现次数的最大值/最小值。

知道最值之后我们就初始化一个 length=maxCnt + 1 的数组用来模拟桶。

为什么是 maxCnt + 1 呢?来看看桶排序的原理。

图解桶排序

假设存在一个长度为 4nums 数组: 1.png 遍历统计可得各自的出现次数:

{
    1: 2,
    2: 1,
    3: 1
}

其中数字 1 的出现次数最多,为两次。所以初始化一个 length = 2 + 1 的数组,其中每个元素都是一个空数组。

new Array(3).fill(0).map(()=>[]) // [[],[],[]]

那么我们已经知道最大出现次数为 3,桶排序就是将元素按出现的次数丢进对应的桶里。

按出现次数丢进桶里,最后得到的二维数组:

[[],[2,3],[1]]

回到正题

那么理解了桶排序之后,这道题的思路也很明确了,创建一个对象 mp 用来计数,一个 maxCnt 用来统计最大值,得到数据后创建一个桶 buckets,遍历对象 mp,根据 value 为下标将 key 丢入对应下标的桶里。最后从后往前输出 k 个元素。

题解

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    const lens = nums.length;
    let maxCnt = -Infinity;

    const mp = {};
    for(let i=0; i<lens; ++i) {
        const k = nums[i];
        mp[k]++ || (mp[k] = 1);
        if(mp[k] > maxCnt) maxCnt = mp[k]
    }
    const buckets = new Array(maxCnt + 1).fill(0).map(()=>[]), res = [];
    for(const [k, v] of Object.entries(mp)) {
        buckets[v].push(k);
    }
    for(let i=buckets.length-1; i>=0; --i) {
        let lens = buckets[i].length, index = 0;
        while(index < lens) {
            res.push(buckets[i][index]);
            if(res.length === k) return res;
            index++;
        }
    }
};

微信截图_20220819020202.png

解题思路——hashmap + 排序

通过 hashmap + sort 的思路也是需要一个对象 mp 来统计出现的次数。

因为题目需要的是前 k出现频率最高的元素。那么我们可以将这个 mp 统计次数的对象按照 value 出现次数来降序排序,最后输出前 k 个就好了。

题解

var topKFrequent = function(nums, k) {
    const lens = nums.length;
    const mp = {};
    for(let i=0; i<lens; ++i) {
        const k = nums[i];
        mp[k]++ || (mp[k] = 1);
    }
    return Object.entries(mp).sort((a,b)=>b[1]-a[1]).slice(0, k).map(item=>item[0]);
};

微信截图_20220819014640.png