剑指Offer——最小的K个数
题目描述:
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
分析:
建一个K大小的大根堆,存储最小的k个数字。
先将K个数进堆,然后调整堆为大根堆。
之后每加一个数,就和堆的根结点比较。
如果大于堆的根结点,则忽略。否则,替换根结点的值,然后调整堆。
最后,剩下的就是其中最小的K个数。
代码:
1 class Solution { 2 public: 3 vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { 4 int iSize = input.size(); 5 if(k == iSize) return input; 6 vector<int> leastNumbers; 7 if(k <= 0 || k > iSize) return leastNumbers; 8 leastNumbers.push_back(0); // 使下标为0的位置为0,不使用该位置,便于访问后面的元素 9 for(int i = 0; i < k; i++) { // 初始化一个k大小的堆 10 leastNumbers.push_back(input[i]); 11 } 12 for(int i = k / 2; i > 0; --i) { 13 HeapAdjust(leastNumbers, i, k); // 调整为大根堆 14 } 15 for(int i = k; i < iSize; i++) { 16 if(input[i] < leastNumbers[1]) { 17 leastNumbers[1] = input[i]; 18 HeapAdjust(leastNumbers, 1, k); // 调整为大根堆 19 } 20 } 21 leastNumbers.erase(leastNumbers.begin()); // 移除第0位置的0 22 return leastNumbers; 23 } 24 25 void HeapAdjust(vector<int> &input, int s, int m) { // 调整堆 26 int rc = input[s]; 27 for(int j = (s << 1); j <= m; j <<= 1) { 28 if(j < m && input[j] < input[j + 1]) ++j; 29 if(rc > input[j]) break; 30 input[s] = input[j]; 31 s = j; 32 } 33 input[s] = rc; 34 } 35 };