当前位置: 首页 > news >正文

对顶堆简介 → 第K大问题 + topK问题

【对顶堆】
对顶堆由一个
大根堆G和一个小根堆L构成,且常以小根堆L的堆顶元素L.top()作为对顶堆的分界点,并满足G.top()<L.top()。 换句话表述,就是“在对顶堆中,大根堆的元素都小于L.top(),小根堆的元素都大于L.top()”。显然,若输入的元素大于L.top(),就加入小根堆。反之,就加入大根堆。 对顶堆常见的示意图如右所示。

由于堆常借助于STL中的 priority_queue<int> 来实现,那么对顶堆便可利用 priority_queue<int> 同时声明一个大根堆G及一个小根堆L来实现。对顶堆代码如下所示:

priority_queue<int> G;    //大根堆  
priority_queue<int,vector<int>,greater<int> > L;    //小根堆

【对顶堆 → 第K大问题】
对顶堆常用于求解“
第K小元素”及“第K大元素”问题。因为优先队列priority_queue虽然不像数组那样支持随机访问,但它可以用O(1)的时间查询出堆顶元素。显然,利用对顶堆查询堆顶元素的时间复杂度与数组的随机访问的时间复杂度O(1)持平。特别是当遇到多次动态查询问题时,对顶堆就更高效。此外,对顶堆还可用于解决其他“第K小元素”及“第K大元素”问题的变形问题,如求前n个元素的中位数等问题。
求解“第 K 大元素”问题的解题思路为:若求第 K 大的元素,先利用输入序列提供的前 K 个元素构建一个包括 K 个元素的小根堆 L,后来的元素 x 先与小根堆 L 的堆顶元素 L.top() 比较,如果 x<L.top(),则将 x 加入大根堆 G;否则,将小根堆 L 的堆顶元素 L.top() 弹出后,将 x 加入小根堆 L。当然,
简洁设计方案是利用输入序列提供的前 K 个元素构建一个包括 K 个元素的小根堆 L,便可求解“第 K 大元素”问题。
“第 K 大元素”问题的代码如下所示。

#include<bits/stdc++.h>
using namespace std;

priority_queue<int,vector<int>,greater<int> > L; //Small Root Heap
priority_queue<int> G; //Big Root Heap

int main() {
    int n,k,x;
    cin>>n>>k;
    while(n--) {
        cin>>x;
        if(L.size()<k) L.push(x);
        else if(x>L.top()) {
            G.push(L.top()); //Optional
            L.pop();
            L.push(x);
        }
    }
    cout<<L.top()<<endl;

    return 0;
}

【topK问题】
topK 问题”指从包含 ‌n 个元素的数据集‌中高效获取前 K 个最大或最小元素‌的算法问题,常见于排行榜、实时数据筛选等场景(如百万用户中筛选前100名活跃用户)‌。topK问题可以利用对顶堆来求解。
“topK 问题”问题的代码如下所示。

#include<bits/stdc++.h>
using namespace std;

priority_queue<int,vector<int>,greater<int> > L; //Small Root Heap
priority_queue<int> G; //Big Root Heap

int main() {
    int n,k,x;
    cin>>n>>k;
    while(n--) {
        cin>>x;
        if(L.size()<k) L.push(x);
        else if(x>L.top()) {
            G.push(L.top()); //Optional
            L.pop();
            L.push(x);
        }
    }

    while(!L.empty()) {
        cout<<L.top()<<" ";
        L.pop();
    }

    return 0;
}

显见,“topK”问题的代码与“第K大元素”问题的代码差别极小。
只需将语句 cout<<L.top()<<" "; 修改为如下语句即可。

while(!L.empty()) {
    cout<<L.top()<<" ";
    L.pop();
}










 

相关文章:

  • 设计心得——作用域处理
  • Cross-Site Scripting: DOM $(_config.elem).html 解决问题
  • 【C++11】左值引用、右值引用、移动语义和完美转发
  • 预测性维护:Ubuntu边缘计算机如何降低电梯故障率
  • rust Send Sync 以及对象安全和对象不安全
  • acwing1295. X的因子链
  • Kubernetes - Pod控制器 - Deployment - 金丝雀部署
  • OpenHarmony 入门——ArkUI 跨页面数据同步和页面级UI状态存储LocalStorage小结(二)
  • java使用Apache POI 操作word文档
  • leetcode684.冗余连接
  • 021-TCMalloc
  • embeddings
  • 查看visual studio的MSVC版本的方法
  • 论华为 Pura X 折叠屏性能检测
  • 使用 OpenCV 拼接进行图像处理对比:以形态学操作为例
  • 【Linux网络-NAT、代理服务、内网穿透】
  • 国产开发板—米尔全志T113-i如何实现ARM+RISC-V+DSP协同计算?
  • 深入理解 JavaScript/TypeScript 中的假值(Falsy Values)与逻辑判断 ✨
  • e2studio开发RA4L1(15)----配置RTC时钟及显示时间
  • 阿里云搭建docker私有仓库
  • 泽连斯基启程前往土耳其
  • 220名“特朗普币”持有者花1.48亿美元,获邀与特朗普共进晚餐
  • 专访|导演刘江:给谍战题材注入现实主义的魂
  • 退休10年后,70岁成都高新区管委会原巡视员王晋成被查
  • 苹果或将于2027年推出由玻璃制成的曲面iPhone
  • 宇树科技王兴兴:第一桶金来自上海,欢迎上海的年轻人加入