题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
分析:这道题最简单的思路莫过于把输入的n个整数排序,这样排在最前面的k个数就是最小的k个数。只是这种思路的时间复杂度为O(nlogn)。我们试着寻找更快的解决思路。
我们可以开辟一个长度为k的数组。每次从输入的n个整数中读入一个数。如果数组中已经插入的元素少于k个,则将读入的整数直接放到数组中。否则长度为k的数组已经满了,不能再往数组里插入元素,只能替换了。如果读入的这个整数比数组中已有k个整数的最大值要小,则用读入的这个整数替换这个最大值;如果读入的整数比数组中已有k个整数的最大值还要大,则读入的这个整数不可能是最小的k个整数之一,抛弃这个整数。这种思路相当于只要排序k个整数,因此时间复杂可以降到O(n+nlogk)。通常情况下k要远小于n,所以这种办法要优于前面的思路。
- 参考代码:
- #include <set>
- #include <vector>
- #include <iostream>
- using namespace std;
- typedef multiset<int, greater<int> > IntHeap;
- ///
- // find k least numbers in a vector
- ///
- void FindKLeastNumbers
- (
- const vector<int>& data, // a vector of data
- IntHeap& leastNumbers, // k least numbers, output
- unsigned int k
- )
- {
- leastNumbers.clear();
- if(k == 0 || data.size() < k)
- return;
- vector<int>::const_iterator iter = data.begin();
- for(; iter != data.end(); ++ iter)
- {
- // if less than k numbers was inserted into leastNumbers
- if((leastNumbers.size()) < k)
- leastNumbers.insert(*iter);
- // leastNumbers contains k numbers and it's full now
- else
- {
- // first number in leastNumbers is the greatest one
- IntHeap::iterator iterFirst = leastNumbers.begin();
- // if is less than the previous greatest number
- if(*iter < *(leastNumbers.begin()))
- {
- // replace the previous greatest number
- leastNumbers.erase(iterFirst);
- leastNumbers.insert(*iter);
- }
- }
- }
- }
题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
1 在数据量不大的情况下,排序
2 维护一个最小k 的数组 ,复杂度 为 o(k * N)
3 为一个最小K个数的最大堆 o(log2 k * N)
题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
1 在数据量不大的情况下,排序
2 维护一个最小k 的数组 ,复杂度 为 o(k * N)
3 为一个最小K个数的最大堆 o(log2 k * N)
- /*
- 查找最小的k 个元素
- 题目:输入n 个整数,输出其中最小的k 个。
- 例如输入1,2,3,4,5,6,7和8这8个数字,
- 则最小的4个数字为1,2,3和4。
- */
- /*
- 思路 : 来一个数据处理一个 ,当来的数据量小于K 时 ,全部处理成最大堆,
- 然后之后来的,必须要小于最大堆的的最大值,才可以入堆,此时 只需更新 根节点,再调整堆。
- */
- # include<stdio.h>
- # include<stdlib.h>
- const int K = 5 ;//这里可以修改
- const int MAXN = 1000;
- int max_heap[K+1] ;//维护一个 最大堆
- int end ,maxPos;
- void swap(int &a ,int &b)
- {
- int t = a;a = b ; b = t;
- }
- int FindMax()
- {
- int maxPos = 1;
- for(int i = 2 ;i <= K ; i ++)
- if(max_heap[i] >max_heap[maxPos] )
- maxPos = i;
- return maxPos;
- }
- /*将数据插入到 数组中 插入排序的思想*/
- void insertMinHeap(int mdata)
- {
- int i,child = 0;
- if(end == K +1 ) // 如果堆满
- {
- /* int mmaxPos = FindMax();*/
- if(mdata >= max_heap[1] ) // 如果大于等于该堆的最大值 不做任何改变
- return ;
- max_heap[1] = mdata;
- for(i = 1 ; i*2 <= K ;i = child)
- {
- child = 2*i ;
- if((i*2 +1 <= K && max_heap[i*2] < max_heap[i*2+1]) )//返回最大孩子的下表
- child ++;
- if(max_heap[i] < max_heap[child])
- swap(max_heap[i] ,max_heap[child]);
- else
- {
- break;
- }
- }
- return ;
- }
- max_heap[end ++] = mdata;
- for(i = end -1 ; i > 1 ; i /=2)
- {
- if(max_heap[i] > max_heap[i/2])
- swap(max_heap[i] ,max_heap[i/2]);
- else
- {
- break;
- }
- }
- }
- int main()
- {
- int n,data;
- freopen("in.txt","r",stdin);//如果想从文件输入 将这句注释掉 1234 1 2 3 4 5 6 7 8 9 10 11
- end = 1;
- while(scanf("%d",&data)!=EOF) // 如果是手工输入 结束输入 按 ctrl + z
- {
- insertMinHeap(data);
- }
- for(int i = 1 ; i <= K ; i ++) //
- printf("%d ",max_heap[i]);
- printf("\n");
- return 0;
- }