在看百度2013校園招聘筆試題,發現如下這道題有必定的思考價值。
題目:有20個數組,每一個數組有500個元素,而且是有序排列好的,如今在這20*500個數中找出排名前500的數。node
這道題一看就知道是個TopK的問題。解決這個問題思路以下:數組是有序的(假設是升序),咱們要利用這個特性。首先構造一個大根堆(大小爲數組個數即20),將每一個數組當前最大的數放入堆中,而後取出大根堆的根,使用一個統計數組(大小爲每一個數組的長度即500)保存這個數,將這個數從大根堆中刪除,接着再向大根堆中放入剛纔刪除的那個數的上一個數(數組是有序的),如此反覆直到統計數組滿了爲止。ios
#include <iostream> #include<cstdlib> #include <set> #include <algorithm> using namespace std; const int N = 20; const int M = 500; int a[N][M];//二維數組存放測試數據 struct node{ int *p; //指向數組中末尾 }; struct classcomp{ bool operator()(const node& left,const node& right) //降序 { return *left.p>*right.p; } }; typedef multiset<node,classcomp> nodeSet; typedef multiset<node,classcomp>::iterator setIterator; int out_put[M]; int out_count=0; int compare (const void * a, const void * b) { return ( *(int*)a - *(int*)b ); } void findTopK(int (&a)[N][M],nodeSet& nodeSet) { node nodeArray[N]; for(int i=0;i<N;i++) { nodeArray[i].p = &a[i][M-1];//指向每一個數組的末尾即每一個數組最大的數 } for(int i=0;i<N;i++) { nodeSet.insert(nodeArray[i]); } while(out_count<M) { setIterator iteratorGreatest = nodeSet.begin(); node n = *iteratorGreatest;//獲取大根 out_put[out_count++] = *n.p;//保存 nodeSet.erase(iteratorGreatest);//刪除 n.p = n.p--;//指針向前移動 nodeSet.insert(n);//插入 } for(int i=0;i<M;i++) { cout<<out_put[i]<<" "; } } int main() { int i,j; //隨機生成數據 for(i=0;i<N;i++) { for(j=0;j<M;j++) { a[i][j]=rand()%256; } } //排序 for(i=0;i<N;i++) { qsort(&a[i][0],M,sizeof(int),compare); } nodeSet nodeSet; findTopK(a,nodeSet); }