题目链接
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按任意顺序返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
pair是C++中一种模板类型。每个pair对象可以存储两个值,这两个值可以是不同的数据类型。存储的值可以是基本数据类型也可以是自定义数据类型。
(1)声明命名空间:using namespace std;
(2)定义和初始化
pair p2(p1); //用已有的对象初始化
pair p3(1, 1.2);
pair p4; //没有显示初始化,自动执行默认初始化操作。p4为(0,0)
make_pair(v1, v2); // 以v1和v2的值创建一个新的pair对象,其元素类型分别是v1和v2的类型。
pair > line; // 创建一个空对象line,两个元素类型分别是string和vector类型
(3)pair有两个属性:first和second。
p1.first = 11; //修改第一个数值
p1.second =22; //修改第二个数值
c++优先队列(priority_queue)用法详解
简单看一下就行了
堆排序参考一(图文)
堆排序参考二(视频)
这是c++11的特性,decltype类型说明符用于取出变量类型。
decltype可以作用于变量、表达式及函数名。①作用于变量直接得到变量的类型;②作用于表达式,结果是左值的表达式得到类型的引用,结果是右值的表达式得到类型;③作用于函数名会得到函数类型,不会自动转换成指针。
decltype不会去真的求解表达式的值。
【C++深陷】之“decltype”
c++的反向迭代器。begin()和end()分别指向数组的首元素和尾元素的下一位。rbegin()和rend()分别指向尾元素和首元素的前一位;sort(vec.rbegin(), vec.rend());就可以获得降序排列的vec,也就是最小值在尾元素。
(虽然本题没有用到)
(1)本题思路:
(2)本题重点在于用优先级队列来对部分频率进行排序。
(3)优先队列不用greater
考虑过使用:priority_queue
,greater小顶堆本以为能得到正确答案。
其实这样无法进行正确的排序,是因为emplace操作默认是比较first,而频数位于second;因此需要自定义比较函数将second作为唯一优先级。
(4)有看到另一种解法:本题的困扰在于pair用的是first来进行排序,那么我们可以将频数保存在first,将num保存在second。①定义一个vector,数据类型为pair,记为s。②不需要使用哈希表,先将nums数组排序,然后直接遍历nums获得某个数的频次(已经排序的数组重复数字必然是连续存放的)将其保存在first。③将s进行反向排序(用到rbegin() , rend()),然后只弹出前k个元素即可。
class Solution {
public:
//1,自定义compare函数
static bool cmp(pair<int, int>& l, pair<int, int>& r) {
return l.second > r.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
//2,使用哈希表存储各个数据的频次
unordered_map<int, int> hashmap;
for(auto& num : nums) {
hashmap[num]++;
}
//3,使用优先队列+小顶堆来对频次排序
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> pri(cmp);
for(auto& [num, count] : hashmap) {
if(pri.size() == k) {
if(pri.top().second < count) {
pri.pop();
pri.emplace(num, count);
}
}
else pri.emplace(num, count);
}
//4,取出前K个高频元素
vector<int> res;
while(!pri.empty()) {
res.push_back(pri.top().first);
pri.pop();
}
return res;
}
};