程序设计题:
3:有20个数组,每个数组有500个元素,并且是有序排列好的,现在在这20*500个数中找出排名前500的数
思路:可以先选出20个数组中最大的数,进行比较,选出其中最大的数,然后再从选出最大的那个数组中选出数放入20个数中比较,每次都重复步骤,直到最终选出500个数,这个复杂度是多少呢?
20个数的比较可以用堆,插入一个数lgn,故总的复杂度是500lg20
用这个思路写出代码如下:
vector< vector<int> > arr; struct CNode { CNode( int data, int num ) { m_data = data; m_num = num; } int m_data; int m_num; }; struct CCmp { bool operator()(const CNode &a, const CNode &b ) { if ( a.m_data == b.m_data ) return a.m_num < b.m_num; else return a.m_data < b.m_data; } }; void Test3() { srand(time(NULL)); arr.resize(20); for ( int i=0; i<20; ++i ) { arr[i].resize(500); for ( int j=0; j<500; ++j ) arr[i][j] = rand(); sort( arr[i].begin(), arr[i].end() ); } // 20 个排序好的数组 priority_queue<CNode,vector<CNode>,CCmp> priq; for ( int i=0; i<20; ++i ) { priq.push(CNode( arr[i].back(), i)); arr[i].pop_back(); } for ( int i=0; i<500; ++i ) { CNode data = priq.top(); // 求出最大的 priq.pop(); cout<<i+1<<"th : "<< data.m_data<<endl; int num = data.m_num; priq.push( CNode( arr[num].back(), num) ); arr[num].pop_back(); }// 求出最大的500个 }
还可以有什么思路呢?我们可以知道每组中最大数和最小数,那此时就可以有个区间,那对20个区间进行排序,此时有几种情况呢?
此时根据上面的思路,我们可以对20段区间进行排序,然后从最大区间中开始找数,然后在找出最大的那些数后,将这些数删除,重新将排除大数的数的区间进行排序,然后重复以上步骤,直到找到500个数。