其他分享
首页 > 其他分享> > 力扣练习——18 前 K 个高频元素

力扣练习——18 前 K 个高频元素

作者:互联网

1.问题描述

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

 

示例 1:

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

输出: [1,2]

示例 2:

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

输出: [1]

 

说明:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。

你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。

输出时,首先输出频率最高的元素,如果频率相同,则先输出元素值较大的元素。

 

可使用以下main函数:

int main()

{

    int n,data,k;

    vector<int> nums;

    cin>>n;

    for(int i=0; i<n; i++)

    {

        cin>>data;

        nums.push_back(data);

    }

    cin>>k;

    vector<int> res=Solution().topKFrequent(nums,k);

    for(int i=0; i<res.size(); i++)

    {

        if (i>0)

            cout<<" ";

        cout<<res[i];

    }

    return 0;

}

 

2.输入说明

首先输入nums数组的长度n,

然后输入n个整数,以空格分隔。

最后输入k。

3.输出说明

首先输出频率最高的元素,如果频率相同,则先输出元素值较大的元素。

元素之间以空格分隔。

4.范例

输入

8
1 1 1 2 2 3 3 4
3

输出

1 3 2

5.代码

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

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        
        map<int, int> map;//注意map的用法
        for(int i:nums)//迭代遍历nums中元素并放入map中  ,注意 i用来代表nums中的每个元素
            map[i] ++; 

        //优先级队列实现最小堆算法
        //1.优先队列没有front()函数与 back()函数,而只能通过top()函数来访问队首元素(也可以称为堆顶元素),也就是优先级最高的元素。
        //2.priority_queue又称为优先队列,其底层是用堆来进行实现的。在优先队列中,队首元素一定是当前队列中优先级最高的那一个。
        //第二个参数vector<>是用来承载底层数据结构堆(heap)的容器;
        //第三个参数less<>或者greater<>是对第一个参数的比较类,less<int>表示数字越大优先级越大,greater<int>表示数字越小,优先级越大。
        //3.关于vector< pair<int, int> >用法:类似于map,但map会对插入的元素按键自动排序,而且不允许键重复。vector的这种用法不会自动排序,而且允许重复。
        
        priority_queue< pair<int, int>, vector< pair<int, int> >, greater< pair<int, int> > > Q; 
        //其中greater< pair<int,int> >会在first相等时比较second

        // 遍历map,维护一个大小为K的小顶堆
        for (auto it : map)//c++11以后用aoto遍历map
            if (Q.size() == k)
            { //队列满了,替换头元素,重新排序堆
                if (it.second > Q.top().first)//it指代map中元素,it.second指向频率;而Q.top().first指向堆顶元素的频率大小
                { //堆排
                    Q.pop();
                    Q.push(make_pair(it.second, it.first));//先根据元素出现频率排序,再根据元素大小排序
                }
            }
            else//小于K直接插入
                Q.push(make_pair(it.second, it.first));//这边插入时,pair<频率,元素值> 
        vector<int> res;
        while (Q.size()) { //将优先队列中k个高频元素存入vector
            res.push_back(Q.top().second);//注意,这边second指向元素值
            Q.pop();
        }
        return vector<int>(res.rbegin(), res.rend());//反向迭代器 ,思考下为什么?解答:因为小顶堆是堆顶元素一个个弹出来的,
                                                     //也就是前K个中频率最低的那个元素,先进入到res中,所以最后的结果肯定要逆序输出!
    }

};



int main()

{

    int n, data, k;

    vector<int> nums;

    cin >> n;

    for (int i = 0; i < n; i++)

    {

        cin >> data;

        nums.push_back(data);

    }

    cin >> k;

    vector<int> res =Solution().topKFrequent(nums, k);

    for (int i = 0; i < res.size(); i++)

    {

        if (i > 0)

            cout << " ";

        cout << res[i];

    }

    return 0;

}

 

标签:map,nums,int,18,元素,力扣,vector,res,高频
来源: https://www.cnblogs.com/juillard/p/16471915.html