寻找最小的k个数(大顶堆方法)

题目描述:查找最小的k个元素,输入n个整数,输出其中最小的k个。

一般的排序方法,如快排,时间复杂度为O(n*logn+k);

大顶堆方法,时间复杂度为O(k+(n-k)*logk);

如果建立k个元素的最小堆的话,那么其空间复杂度势为O(N),而建立k个元素的最大堆的空间复杂度为O(k);

当面对海量数据处理的时候,大顶堆的方法是较为靠谱的,并且可以在面试时短时间内完成代码。

 1 class Solution {
 2 public:
 3     void Swap(int &a,int &b)
 4     {
 5         a^=b;
 6         b^=a;
 7         a^=b;
 8     }
 9
10     void HeapAdjust(vector<int> &input,int i,int k)
11     {
12         int max = i;
13         int leftchild = 2*i;
14         int rightchild = 2*i+1;
15
16         if(i<=k/2)
17         {
18             if(input[leftchild] > input[max] && leftchild <= k)
19             {
20                 max = leftchild;
21             }
22             if(input[rightchild] > input[max] && rightchild <= k)
23             {
24                 max = rightchild;
25             }
26             if(max!=i)
27             {
28                 Swap(input[i],input[max]);
29                 HeapAdjust(input,max,k);
30             }
31         }
32     }
33
34     void BuildHeap(vector<int> &input,int k)
35     {
36         for(int i = k/2;i >0;i--)
37         {
38             HeapAdjust(input,i,k);
39         }
40     }
41
42     vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
43         vector<int> result;
44         vector<int> temp;
45         int len = input.size();
46         if(k>len)
47             return result;
48
49         temp.push_back(0);
50         for(int i = 0;i < len;i++)
51         {
52             temp.push_back(input[i]);
53         }
54
55         BuildHeap(temp,k);
56
57         for(int i = k+1;i <= len;i++)
58         {
59             if(temp[i] < temp[1])
60             {
61                 temp[1] = temp[i];
62                 HeapAdjust(temp,1,k);
63             }
64         }
65
66         for(int i = 0;i < k;i++)
67         {
68             result.push_back(temp[i+1]);
69         }
70         return result;
71     }
72 };

PS:类似快速排序的partition过程,时间复杂度可以做到O(N)。

时间: 2024-10-06 00:25:33

寻找最小的k个数(大顶堆方法)的相关文章

寻找最小的k个数(四种方法)

1 使用从大到小的优先队列保存最小的K个数,每次取出K个数之后的其余数和堆顶元素比较,如果比堆顶元素小,则将堆顶元素删除,将该元素插入 void topK(int arr[],int n,int k) { if(k>n) return; priority_queue<int> q; for(int i=0;i<n;++i) { if(q.size()<k) q.push(arr[i]); else { if(arr[i]<q.top()) { q.pop(); q.pu

寻找最小的K个数

寻找最小的K个数 题目描述:查找最小的K个数 题目:输入n个整数,输出其中最小的K个数 例如,输入1.2.3.4.5.6.7.8这8个数字,则最小的4个数字为1.2.3.4. 第一节.各种思路,各种选择 要求一个序列中最小的K个数,按照惯有的思维方式,很简单,先对这个序列从小到大排序,然后输出前面的最小的K个数即可: 至于选取什么样的排序方法,第一时间应该想到的是快速排序,我们知道,快速排序平均时间复杂度为O(nlogn),然后再遍历序列中前K个元素输出,即可,总的时间复杂度为O(nlogn +

寻找最小的k个数(update)

类似编程之美中寻找最大的k个数 解法一: 题目没有要求最小的k个数有序,也没要求最后n-k个数有序.既然如此,就没有必要对所有元素进行排序.这时,咱们想到了用选择或交换排序,即: 1.遍历n个数,把最先遍历到的k个数存入到大小为k的数组中,假设它们即是最小的k个数: 2.对这k个数,利用选择或交换排序找到这k个元素中的最大值kmax(找最大值需要遍历这k个数,时间复杂度为 O(k) ): 3.继续遍历剩余n-k个数.假设每一次遍历到的新的元素的值为x,把x与kmax比较:如果 x < kmax

剑指offer:数据流中的中位数(小顶堆+大顶堆)

1. 题目描述 /** 如何得到一个数据流中的中位数? 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值. 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 我们使用 Insert()方法读取数据流,使用 GetMedian()方法获取当前读取数据的中位数. */ 2. 思路 /** 最大堆和最小堆 * 每次插入小顶堆的是当前大顶堆中最大的数 * 每次插入大顶堆的是当前小顶堆中最小的数 * 这样保证小顶堆中的数永远大于等于大顶堆中的数(值

O(n)时间复杂度求最小的k个数和第k小的数

//思路:使用快速排序的patition函数来进行处理 时间复杂度为O(n) #include<iostream> #include<cassert> using namespace std; int partition(int *ar, int len, int low, int high) { int temp = ar[low]; while(low < high) { while(low < high && temp < ar[high])

寻找最大或最小的K个数

题目描述 :在好几亿个数据中找出最大或最小的K个数. 分析:这几亿的数据肯定不能一起加载到内存中去,更不能对这些数据直接进行排序,因此我们这里讲用数据结构中的 堆 来解决这个问题. 假定这里要从100000个数据中找出最大的100个数据,这样是为了描述方便,我们这里直接用一个数组来存储这个100000个数据,如果数据多达好几亿,则只需将这些数据放入文件中进行读写即可,这里为了描述问题方便就这样假定. 步骤: 取出这些数据中前100个数据,然后用这些数据建立一个小堆: 从第101个数据开始,每读取

poj 2010 Moo University - Financial Aid 大顶堆维护最小和

题意: 有c有牛,从中选(n-1)/2头,使他们的得分中位数最大且需要的资金援助和不超过f. 分析: 堆的运用大顶堆维护最小和. 代码: //poj 2010 //sep9 #include <iostream> #include <queue> #include <algorithm> using namespace std; const int maxN=100024; int dpl[maxN],dpr[maxN]; priority_queue<int&g

找到n中最小的k个数

题目:n个数中,求最小的前k个数. 这道题在各个地方都看到过,在国内出现的频率也非常高. 解法: 1. brute force. O(k*n)复杂度: 2. sort.O(k+n*lgn)复杂度: 3. 最大堆.每次替代的是大小为k的最大堆的最大值.O(k+(n-k)lgk)复杂度. 4. 最小堆.和sort类似,只是建堆后只求前k次.O(n+k*lgn)复杂度.在网上看到一个优化,就是pop出第k小的数(堆顶)的时候,最多只需要调整k-1层(不需要调到堆底).所以可以优化到O(n+k^2).当

剑指Offer28 最小的K个数

包含了Partition函数的多种用法 以及大顶堆操作 1 /************************************************************************* 2 > File Name: 28_KLeastNumbers.cpp 3 > Author: Juntaran 4 > Mail: [email protected] 5 > Created Time: 2016年08月31日 星期三 19时45分41秒 6 *******