leetcode 347. 前K个高频元素

147 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

前言

今天继续练习栈与队列方面的算法题,做到leetcode 347.前K个高频元素,通过这道题又学习了优先队列的概念,分享并记录一下。

题目

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

思考

对于题目要求找出出现频率前k高的元素,我们需要计算出元素出现的频率,很容易想到用Map的方式统计:

countMap.set(num, (countMap.get(num) || 0) + 1)

有很多相似的题也可以通过Map的方式解决。

但是这不是这道题的核心点,核心是要把计算出的频率排序并输出k个高频元素。通过查找资料以及看了一些大佬的题解,我发现了一个新的知识——优先级队列,那么什么是优先级队列呢?

优先级队列

优先级队列本质上是一个堆结构,但由于其从对头取元素,从队尾添加元素,所以看起来像是一个队列。优先级队列通过堆的方式排序。学过数据结构的人知道,堆就是一颗完全二叉树,大顶堆根节点大于其左右孩子的值,小顶堆根节点小于其左右孩子的值。

那么我们就可以采用小顶堆,每次将最小的元素弹出,最终留下最大的k个元素,就是最终的结果。

注意:js与ts没有最小堆的数据结构,所以直接对整个数组进行排序,取前k个元素

代码实现

function topKFrequent(nums: number[], k: number): number[] {
    const countMap: Map<number, number> = new Map();
    for (let num of nums) {
        countMap.set(num, (countMap.get(num) || 0) + 1);
    }
    // tS没有最小堆的数据结构,所以直接对整个数组进行排序,取前k个元素
    return [...countMap.entries()]
        .sort((a, b) => b[1] - a[1])
        .slice(0, k)
        .map(i => i[0]);
};