力扣刷题日志——347. 前 K 个高频元素

力扣刷题日志——347. 前 K 个高频元素

题干

给你一个整数数组 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 个高频元素的集合是唯一的

**进阶:**你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。

思路

  1. 计算出元素出现的频率(考虑使用map)
  2. 按元素出现次数进行排序(优先级队列)
  3. 输出频率前k高的元素

什么是优先级队列(priority_queue)?

一个披着队列外衣的堆

对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列

内部实现

默认情况下,利用max-heap(大根堆)完成对元素的排序。这个大根堆是以vector为表现形式的complete binary tree(完全二叉树)

为什么这道题不用大根堆而是小根堆?

因为,我们限定优先级队列的大小为k后,要留下频率最高的k个数,因此,使用小根堆pop出较小的数,留下的就是频率最大的k个数,这里也没有对输出数组的顺序有要求。

如何使用小根堆优先级队列?

int

#include <iostream>
#include <queue>
using namespace std;

void showpq( priority_queue<int, vector<int>, greater<int> > g) {
    while (!g.empty()) {
        cout <<  ' ' << g.top();
        g.pop();
    }
    cout <<  '\\n';
}

void showArray(int* arr,  int n) {
    for (int i = 0; i < n; i++) {
        cout << arr[i] <<  ' ';
    }
    cout << endl;
}

int main() {
    int arr[6] = { 10, 2, 4, 8, 6, 9 };
    priority_queue<int, vector<int>, greater<int> > gquiz( arr, arr + 6);
    cout <<  "Array: ";
    showArray(arr, 6);
    cout <<  "Priority Queue : ";
    showpq(gquiz);
    return 0;
}

自定义对象

struct Person {
    int age;
};

struct LessThanByAge {
    bool operator()(const Person& lhs, const Person& rhs) const {
        return lhs.age > rhs.age;
    }
};

priority_queue<Person, vector<Person>, LessThanByAge> pq;

在这个例子中,LessThanByAge是一个自定义的比较函数,它将Person对象按照age属性的大小进行排序。这样,pq.top()将返回age最小的Person对象。如果你想让age最大的Person在顶部,你可以改变LessThanByAge操作符的实现

代码实现:

class myComparison
{
public:
    bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) const
    {
        return lhs.second > rhs.second;
    }
};

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        //统计出现的频次
        unordered_map<int,int> map;
        for(auto num : nums)
        {
            map[num]++;
        }
        // 定义一个小顶堆,大小为k
        priority_queue<pair<int,int>,vector<pair<int,int>>,myComparison> pri_que;

        for(unordered_map<int,int>::iterator it = map.begin(); it != map.end(); ++it)
        {
            pri_que.push(*it);
            if(pri_que.size() > k)
            {
                pri_que.pop();
            }
        }
        vector<int> ret(k); 
        for(int i = k - 1; i >= 0; --i)
        {
            ret[i] = pri_que.top().first;
            pri_que.pop();
        }
        return ret;
    }
};
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值