问题来源:左程云:《程序员代码面试指南》第八章
打印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;
}