上位kの問題の解決策。

n個の数があり(nは一般に非常に大きい)、最大のk個の数を見つける方法は?

アイデア:
ヒープを使用して
1 を実現する。最初にnからk個の数値を選択して、小さなトップヒープを構築します。
2.次に、残りのnk数をヒープの上位要素と順番に比較します。
3.比較ごとに、比較結果に応じて異なる処理が行われます。
        1)数値がヒープの一番上の要素より小さい場合、この数値は一番上のkに含まれていてはならず、直接破棄します。
        2)数値がヒープの最上位要素より大きい場合、この数値は最上位kにある可能性があり、最上位要素が最上位kに含まれていてはなりません。最上位要素をこの数値に置き換え、ヒープを再調整します。
        数値がヒープの先頭要素と同じ場合は、1)または2)のいずれかを実行できます1)ヒープ調整を回避できます。
4.すべての数値を比較した後、ヒープ内の残りの要素はトップkです。

時間の複雑さ:
ヒープを構築するとき、要素を追加するにはlogkが必要です。比較する場合、各比較にはlogkが必要です。チーム編成中に追加された要素の数+比較の数= n。時間の複雑さはO(n log k)
空間の複雑さ:
ヒープサイズ、O(k)

C ++の実装:

#include <queue>
#include <vector>
#include <cstdio>
using namespace std;

void topK(const vector<int> & input ,vector<int> & result, int k){
    
    

    priority_queue<int, vector<int>,greater<int>> pq;

    for(int i=0; i<k; i++)
        pq.push(input[i]);

    for(int i=k; i<input.size(); i++){
    
    
        if(input[i]<=pq.top())
            ;
        else if(input[i]>pq.top()){
    
    
            pq.pop();
            pq.push(input[i]);
        }
    }

    result.clear();
    for(int i=0; i<k; i++) {
    
    
        result.push_back(pq.top());
        pq.pop();
    }

}



int main() {
    
    
    vector<int> input;
    vector<int> result;
    int t,n,k;

    scanf("%d%d", &n, &k);

    while(scanf("%d", &t)==1)
        input.push_back(t);

    topK(input, result, k);

    for(auto it=result.begin(); it!=result.end(); it++)
        printf("%d ", *it);
    printf("\n");

    return 0;
}

おすすめ

転載: blog.csdn.net/wx_assa/article/details/107878975