当前位置:   article > 正文

Leetcode刷题-347:前 K 个高频元素_class solution { public: vector topkfrequent(

class solution { public: vector topkfrequent(vector& nums, int k)

1.题目描述

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

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

示例2:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-elements

2.题目分析

2.1 使用优先队列

前面的文章已经介绍过优先队列解题的思路,这篇文章对优先队列的介绍很详细。这道题依然可以使用一个存储pair数据的优先队列priority_queue来解题。此时pair中的k-v关系应当是:频率-元素值;因为默认的优先队列是一个大顶堆,所以我们直接使用它的话就选择将数组内所有的频率-元素值对存储到优先队列中,此时会根据频率进行自动的排序,到所有的pair元素插入队列之后,我们输出k次堆顶元素(也就是队首元素),就完成了最高频的前k个元素。

对于优先队列所需要存储的频率-元素值对的求法,可以通过对数组进行排序,然后在再次遍历数组的时候累计求得。具体代码如3.1所示。

2.2 使用小顶堆

前面直接使用大顶堆的话,虽然时间复杂度上较为可以,但是我们发现,需要存储所有元素的频率-元素值对,这就造成很大的空间浪费。既然题目是要求我们求解前k个高频元素,那么其实我们每次只维护k个元素的队列就可以了。我们可以设想出这样的流程

在一个空间维护k个元素,每当有一个新的元素P需要加入的时候,我们就看这个空间的最小的元素min是否大于这个待加入元素。如果min>P,则说明P不是前k个最大的元素;否则的话,p>min,min就应该被淘汰。

但这样的话是无法靠大顶堆实现的。因为大顶堆的堆顶是最大元素,而且我们无法简单的查找出当前堆哪个元素最小。与大顶堆对应的一个数据结构——小顶堆,则可以实现这样的操作。于是我们试图用小顶堆来进行优先队列的初始化。

2.3 基于快排的partition算法划分数组

既然是求前k个值,那么我们可以想到快排中的partition算法就是根据基准元素将数组划分为两个部分,基准元素前面和后面的分别可以是大于基准元素和小于基准元素的值。这就很契合我们这道题了。快排的具体实现可以看这篇文章

在这道题运用快排基准划分的方法的话,我们需要将map保存的键值对存储到vector进行处理,因为vector可以进行高效的基于下标的交换元素。但是由于各个数据结构的特性,在元素值-频率键值对存储的时候还是要用到map结构。

所以我们的实现代码就如3.3所示,代码注释解释了解题思路。

3.题目解答

3.1 直接使用优先队列——大顶堆

class Solution {
   
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
   
        int len = nums.size();
        sort(nums.begin(),nums.end());
        priority_queue<pair<int,int>> que;
        for(int i
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/72775
推荐阅读
相关标签
  

闽ICP备14008679号