今天复习一下堆的知识。
先手写复现一边堆排序,C++代码如下。
代码写的是小顶堆。
void heap_build(vector &arr,int i,int size){
int l=2*i+1;
int r=l+1;
int flag=i;
if(larr[flag]){
flag=l;
}
if(rarr[flag]){
flag=r;
}
if(flag!=i){
swap(arr[flag],arr[i]);
heap_build(arr, flag, size);
}
}
void heap_sort(vector &arr,int size){
for(int i=size/2-1;i>=0;--i){
heap_build(arr, i, size);
}
for(int j=size-1;j>=0;--j){
swap(arr[0],arr[j]);
heap_build(arr, 0, j);
}
}
复杂度为O(nlogn)
堆排序是解决topK问题的好方法。
leetcode215
在未排序的数组中找到第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
方法1: 直接用priority_queue优先队列实现
//C++ 优先队列默认大顶堆,若用小顶堆则可变为负数
class Solution {
public:
int findKthLargest(vector& nums, int k) {
priority_queue q;
for(int i=0;i
方法2: 自己定义堆实现
利用之前的构建堆方法,构造一个k大小的小顶堆,再把接下来每个元素与堆顶进行比较。若大于堆顶,就弹出堆顶,插入当前元素,再次排序。
//
// main.cpp
// t
// heap implementation
//
// Created by Fang Hantao on 2020/12/30.
//
#include
#include
#include
using namespace std;
void heap_build(vector &arr,int i,int size){
int l=2*i+1;
int r=l+1;
int flag=i;
if(larr[flag]){
flag=l;
}
if(rarr[flag]){
flag=r;
}
if(flag!=i){
swap(arr[flag],arr[i]);
heap_build(arr, flag, size);
}
}
void heap_sort(vector &arr,int size){
for(int i=size/2-1;i>=0;--i){
heap_build(arr, i, size);
}
for(int j=size-1;j>=0;--j){
swap(arr[0],arr[j]);
heap_build(arr, 0, j);
}
}
// 返回第二个大的数 k=2
int main(int argc, const char * argv[]) {
vectorarr={3,2,1,5,6,4,9,7};
int k=2;
heap_sort(arr,k);
vector brr=arr;
for(int i=3;iarr[0]){
arr[0]=a;
heap_sort(arr,k);
}
}
cout<
leetcode347
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
本题思路很清晰,唯一问题就是堆排序的数据应该是出现次数。
参考了题解,将堆的数据类型设置为pair
class Solution {
public:
static bool cmp(pair& m, pair& n) {
return m.second > n.second;
}
vector topKFrequent(vector& nums, int k) {
int n=nums.size();
unordered_map mp;
for(auto a : nums){
mp[a]++;
}
priority_queue,vector>,decltype(&cmp)> q(cmp);
auto it=mp.begin();
for(it;it!=mp.end();++it){
if(q.size()==k){
if(it->second>q.top().second){
q.pop();
q.push(make_pair(it->first,it->second));
}
}
else{
q.push(make_pair(it->first,it->second));
}
}
vector arr;
while(!q.empty()){
arr.push_back(q.top().first);
q.pop();
}
return arr;
}
};
其中,这段代码我觉得值得好好学习。我一开始也看不懂,后来翻了stl源码才理解。 还是知道的太少了。不能局限在int类型,思路太窄。
priority_queue,vector>,decltype(&cmp)> q(cmp);
// 第一个参数为数据类型T,第二个为组成的序列,第三个相当于排序规则。