面试常见题之TopK问题
2017-03-30 08:38
381 查看
一:堆的一个应用就是优先级队列:
优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。
如:
二:Topk问题:
问题描叙:在N(N>>10000)个数据中找到最大的K个数
分析;这时海量数据的问题,只要前K个,输出整个数据的保存和排序都是不可取的,我们可以建一个小堆用来保存这k个数据,然后再那N-K个数据与小堆的最小值比较,大的数据进堆,直到N-K数据比较完为止
时间复杂度为O(N*logK)
优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。
如:
template<class T,class Compare =Greater<T>> class PriorityQueue { public: void Push(const T&x) { _hp.Push(x); } void Pop() { _hp.Pop(); } size_t Size() { return _hp.Size(); } bool Empty() { return _hp.Empty(); } const T&Top() { return _hp.Top(); } protected: Heap<T, Compare>_hp; }; void TestPriorityQueue() { int a[] = { 14, 10, 56, 7, 83, 22, 36, 91, 3, 47 }; PriorityQueue<int, Greater<int>> hp; for (size_t i = 0; i < 10; i++) { hp.Push(a[i]); } while (!hp.Empty()) { cout << hp.Top() << " "; hp.Pop(); } cout << endl; }
二:Topk问题:
问题描叙:在N(N>>10000)个数据中找到最大的K个数
分析;这时海量数据的问题,只要前K个,输出整个数据的保存和排序都是不可取的,我们可以建一个小堆用来保存这k个数据,然后再那N-K个数据与小堆的最小值比较,大的数据进堆,直到N-K数据比较完为止
#pragma once #include<iostream> #include<queue> #include<assert.h> using namespace std; #define N 1000 #define K 10 template<class T> void AdjustDown(T*heap,size_t root) { size_t parent = root; size_t child = parent * 2 + 1; while (child< K) { //找最小的孩子 if (child + 1 < K&& heap[child+1] < heap[child]) { child++; } if (child <K&&heap[child] < heap[parent]) { swap(heap[child], heap[parent]); parent = child; child = parent * 2 +1; } else { break; } } } //堆里面存放k个数据 template<class T> void Topk( T*a, T*heap) { assert(N > K); for (size_t i = 0; i < K;++i) { heap[i] = a[i]; } //调整成小堆 for (int j = (K - 2) / 2; j >= 0; --j) { AdjustDown(heap,j); } //如果数组里面的数据比堆里面的最小值大则入堆; for (size_t i = K; i < N; ++i) { if (a[i]>heap[0]) { swap(a[i], heap[0]); AdjustDown(heap,0); } } } template<class T> void Print(T *heap) { int k = 10; for (size_t i = 0; i < K; i++) { cout << heap[i] << " "; } cout << endl; } void TestTopK() { int a = {0}; int heap[K] = {0}; for (int i = 0; i < N; ++i) { a[i] = i; } Topk(a,heap); Print(heap); }
时间复杂度为O(N*logK)