面試題: 求N個數中前k個大的數(大資料)
阿新 • • 發佈:2019-02-05
解題思路:一般思路就是將N個數排序後,取前k個數就ok。但是如果N個數是幾十億個數,載入不到記憶體怎麼辦?這就需要另外一種思路了,那就是利用堆。
具體的思路是:先建一個k個數的小堆,然後從k+1個數往後的值與堆頂元素比較,若此數比堆頂元素大,就將堆頂元素用這個數替換,然後重新調整堆,以此向後重複上述過程,直到將N個數比較完成,那麼此時組成這個堆的k個元素就是前k個大的數。
下邊是具體實現的程式碼:
#pragma once #include<iostream> #include<vector> using namespace std; template<class T> class Heap { public: Heap(const T* a, int k) { _CreateHeap(a, k); } void Push(const T& x) { _a.push_back(x); _AdjustUp(_a.size() - 1); } T& Top() { return _a[0]; } void BuildHeap(const T* a, int k) { for (int i = (k - 2) / 2; i >= 0; i--) { _AdjustDown(i); } } void Print() { for (int i = 0; i < _a.size(); i++) { cout << _a[i] << " "; } cout << endl; } public: void _CreateHeap(const T* a, int k) { for (int i = 0; i < k; i++) { _a.push_back(a[i]); } //建小堆 for (int i = (k - 2) / 2; i >=0; i--) { _AdjustDown(i); } } void _AdjustDown(int parent) //向下調整 { int child = parent * 2 + 1; while (child < _a.size()) { if (child + 1 < _a.size() && _a[child] > _a[child + 1]) { child++; } if (_a[child] < _a[parent]) { swap(_a[child], _a[parent]); parent = child; child = parent * 2 + 1; } else { break; } } } //void _AdjustUp(int child)//向上調整 //{ // int parent = (child - 1) / 2; // while (child >= 0) // { // if (_a[child] > _a[parent]) // { // swap(_a[child], _a[parent]); // child = parent; // parent = (child - 1) / 2; // } // else // { // break; // } // } //} private: vector<T> _a; };
#include"HeapSort.h" void GetTopK(int* a, int k, int size) { //建堆 Heap<int> hp(a, k); //hp.Print(); //k個數後面的數,比堆頂元素大,則插入 for (int i = k; i < size; i++) { if (hp.Top() < a[i]) { hp.Top() = a[i]; hp._AdjustDown(0); } } hp.Print(); } void Test() { int a[] = { 1, 0, 3, 5, 8, 2, 6, 7, 4, 9, 10, 26, 35, 20, 30, 40 }; int len = sizeof(a) / sizeof(a[0]); int k = 6; for (int i = 0; i < len; i++) { cout << a[i] << " "; } cout << endl; cout << "最大的前" << k << "個數為:" << endl; GetTopK(a,6,len); }