打印N个数组整体最大的Top K

问题来源:左程云:《程序员代码面试指南》第八章

打印N个数组整体最大的Top K:

问题描述:

N个数组用二维数组表示  vector<vector<int>> data
将所有数按照从大到小的顺序进行排序,输出前K个数,但这样在面对海量数据时时间复杂度较高,利用堆的思想进行求解,
步骤:
1、建堆,将每个数组的最后一个数加入堆中,建立一个大小为N的大堆;
2、此时堆顶元素为所有数据中的最大的数据,输出;
3、假设堆顶元素在二维数组中的坐标为(i,j),如果j>0,则将data[i][j-1],加入堆顶,并调整堆;
4、每次打印堆顶元素,并循环打印K次,
5,在第三步中若j==0,即该堆顶元素是其所在数组中的第一个元素,则将堆顶元素和堆的最后一个元素进行交换,同时堆的大小减一,说明其中一个数组遍历完了,接下来只需要N-1 大小的堆就行了。
这题主要是建立堆,堆的节点存储的值分别有,当前值大小,当前值在二维数组中的位置,即第几个数组的第几个数,用于上面的第三步。

#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
bool cmp(int a,int b){
    return a>b;
}
//堆的节点的结构
struct heapNode{
    int val;//当前值
    int col;//二维向量的行
    int row;//二维向量的列
};
void heapinsert(vector<heapNode> &heap,int index);
void heapvify(vector<heapNode> &heap,int index,int heapsize);
void swap(vector<heapNode> &heap,int index1,int index2){
    heapNode tmp=heap[index1];
    heap[index1]=heap[index2];
    heap[index2]=tmp;
}
//输出topK个数
void printtopK(vector<vector<int> > data,int K){
    int heapsize=data.size();
    vector<heapNode> heap;
    for(int i =0;i<data.size();i++){
        int index=data[i].size()-1;
    //新节点插入heap
        heapNode node;
        node.val=data[i][index];
        node.col=i;
        node.row=index;
        heap.push_back(node);
        heapinsert(heap,i);
    }
    for(int i=0;i<K;i++){
        if(heap.size()==0)
            break;
        cout<<heap[0].val<<",";
        if(heap[0].row!=0){
            heap[0].val=data[heap[0].col][--heap[0].row];
        }else{
            swap(heap,0,--heapsize);
        }
        heapvify(heap,0,heapsize);
    }
}
//从index 开始调整堆
void heapvify(vector<heapNode> &heap,int index,int heapsize){
    int largest=index;
    int left=2*index+1;
    int right=2*index+2;
    while(left<heapsize){
        if(heap[left].val>heap[largest].val){
                largest=left;
        }
        if(right<heapsize&&heap[right].val>heap[largest].val){
            largest=right;
        }
        if(largest!=index){
            swap(heap,largest,index);
        }else{
            break;
        }
        index=largest;
        left=2*index+1;
        right=2*index+1;
    }
}
//在index处插入一个元素
void heapinsert(vector<heapNode> &heap,int index){
    while(index!=0){
        int parent=(index-1)/2;
        if(heap[parent].val<heap[index].val){
            swap(heap,index,parent);
            index=parent;
        }else{
            break;
        }
    }
}
vector<int> strtovec(string str){
    vector<int> ret;
    int fast=0;
    int last=0;
    while(fast<str.size()){
        if(str[fast]==','){
            int temp=0;
            for(int i=last;i<fast;i++){
                temp=temp*10+(str[i]-'0');
            }
            ret.push_back(temp);
            fast++;
            last=fast;
        }else{
            fast++;
        }
    }
    int temp=0;
    for(int i=last;i<fast;i++){
        temp=temp*10+str[i]-'0';
    }
    ret.push_back(temp);
    return ret;
}
void printvec(vector<int> data){
    for(int i=0;i<data.size()-1;i++){
        cout<<data[i]<<",";
    }
    cout<<data[data.size()-1]<<endl;
}
int main()
{
    freopen("in.txt","r",stdin);
    vector<vector<int> > test;
    string str="1,2,3,4,5,6,78,90";
    int k;
    cin>>k;
    while(cin>>str){
        vector<int> temp=strtovec(str);
        test.push_back(temp);
    }
    printtopK(test,k);
    return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值