我是靠谱客的博主 诚心月光,最近开发中收集的这篇文章主要介绍求解第K大元素,第K小元素/前k大元素,前k小元素/中位数 (堆·二叉堆) poj1442/black box,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

如何求解一个第k大元素or第k小元素问题呢?/前k大元素or前k小元素

    • 这类问题通常会有两种情况,1· 有序数组求解第k大, 2·无序数组(前k小or前k大)

这类问题通常会有两种情况,1· 有序数组求解第k大, 2·无序数组(前k小or前k大)

通常对于第k大元素问题求解过程如下:
1·我们只需要用一个小顶堆
2·从数组中选择k个元素,加入堆中…按顺序加入即可,最小的元素一定是堆顶元素.
3·数组中剩下的元素依次与堆顶比较.(我们需维护小顶堆)
4·堆顶元素就是第k大堆元素

举例 1 2 3 4 5 求解第3大元素,我们只需要维护 有3个元素堆小顶堆.我们直观的看 第三大的就是3.
一开始将 1 2 3 加入堆中,1在堆顶.
第一轮 1 与 4 比较,大于堆顶元素则1出堆,4入堆 此时 堆顶为2
第二轮 2 与 5比较 同上 堆顶被调整为3
3便是我们需要的答案

第k小元素反之亦然,换成大顶堆

前k大元素 or 前k小元素

如果我们单一的用一个大顶堆或者一个小顶堆,难以解决这类问题
我们可以将这类问题 抽象成 求一个数组里的中位数问题
假设给一个数组 在此借用POJ1442 的Black Box 题目
在这里插入图片描述
在这里插入图片描述
大概解释一下,输入了n个数,m次询问.m次询问就是让我们求前m个元素中,第m小的元素

如果只用一个堆,是没有办法做解决的

所以我们需要使用二叉堆(对顶堆)

所有小堆元素 > 大堆元素,即可在大堆的堆顶找到第m小的元素

#include <iostream> 
using namespace std;
#include <set>
#define MAX 30000
int val[MAX+5] ={0};
typedef pair <int ,int> PII;
set<PII> s1,s2;
int main() {
    int n;
    int m;
    cin >> n>> m;
    for(int i = 1; i <= n; i++){
        cin >> val[i];
    }
    for(int i = 1, j = 0; i <= m; i++) {
        int k;
        cin >> k;
        while ( j < k ) {
            ++j;
            if(s1.size() == 0 || -s1.begin()->first > val[j]){ //
                s1.insert(PII(-val[j],j));
            }else {
                s2.insert(PII(val[j],j));
            }
        }
        while (s1.size() > i) {
            s2.insert(PII(-s1.begin()->first , s1.begin()->second));
            s1.erase(s1.begin());
        }
        while (s1.size() < i) {
            s1.insert(PII(-s2.begin()->first , s2.begin()->second));
            s2.erase(s2.begin());
        }
        cout << -(s1.begin()->first) << endl;
    }
    return 0;
}

最后

以上就是诚心月光为你收集整理的求解第K大元素,第K小元素/前k大元素,前k小元素/中位数 (堆·二叉堆) poj1442/black box的全部内容,希望文章能够帮你解决求解第K大元素,第K小元素/前k大元素,前k小元素/中位数 (堆·二叉堆) poj1442/black box所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部