查找最小的k个元素 【微软面试100题 第五题】
题目要求:
输入n个整数,输出其中最小的k个。
例如:输入1,2,3,4,5,6,7,8这8个数字,则最小的4个数字为1,2,3,4。
参考资料:剑指offer第30题。
题目分析:
解法一:
用快排的思想,但是最小的k个数不用排序,时间复杂度O(n).
优点:时间复杂度好,缺点:会修改原整数数组顺序。
解法二:
创建一个大小为k的最大堆,遍历一遍数组,同时不断修改最大堆。时间复杂度O(nlogk).
优点:不会修改原数组,适用于海量数据。缺点:比解法一时间复杂度高。
其他解法:
1.快排,取前k个数,时间复杂度O(nlogn).
2.遍历k次,时间复杂度O(k*n).
3.位图排序,取前k个数,时间复杂度O(n).会占用额外的空间.
解法一代码:

#include <iostream> #include <stdlib.h> using namespace std; inline int my_rand(int low, int high) { int size = high - low + 1; return low + rand() % size; } int partition(int a[], int low, int high) { int val = a[low]; while(low<high) { while( (low<high) && (a[high]>=val) ) high--; a[low] = a[high]; while( (low<high) && (a[low] <= val) ) low++; a[high] = a[low]; } a[low] = val; return low; } void swap(int *a,int i,int j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } bool rand_select(int array[], int left, int right, int k) { //第k 小元素,实际上应该在数组中下标为 k-1 if (k-1 > right || k-1 < left) return false ; if(left<right) { //随机从数组中选取枢纽元元素 int index = my_rand(left, right); swap(array,index,left); int pos = partition(array , left, right); if(pos == k-1) return true ; else if (pos > k-1) return rand_select(array , left, pos-1, k); else return rand_select(array, pos+1, right, k); } else return true ; } int main() { int array1[] = {7, 8, 9, 12, 6, 4, 11, 1, 2, 33}; int numOfArray = sizeof (array1) / sizeof( int); for(int i=0; i<numOfArray; i++) cout << array1[i] << " "; cout << endl; int K = 5; bool flag = rand_select(array1, 0, numOfArray-1, K); if(flag) { cout << "最小的" << K << "个数为:"; for(int i=0; i<K; i++) cout << array1[i] << " "; cout << endl; } return 0; }
解法二代码:

//从头实现一个最大堆需要一定的代码,可以采用c++中的红黑树来实现。 //其中set和multiset都是基于红黑树实现的,后者可以支持数组中有重复 #include <iostream> #include <set> #include <vector> using namespace std; typedef multiset<int,greater<int>> intSet; typedef multiset<int,greater<int>>::iterator setIterator; void getLeastNumbers(const vector<int> &data,intSet &leastNumbers,int k); int main(void) { int a[8] = {1,2,8,4,5,6,7,3}; const vector<int> data(a,a+8);//8不是7 intSet leastNumbers; int k = 5; getLeastNumbers(data,leastNumbers,k); cout << "最小的" << k << "个数为:"; setIterator iter = leastNumbers.begin(); for(;iter!=leastNumbers.end();++iter) cout << *iter << " "; cout << endl; return 0; } void getLeastNumbers(const vector<int> &data,intSet &leastNumbers,int k) { leastNumbers.clear(); if(k<1 || k>data.size()) return ; vector<int>::const_iterator iter = data.begin(); for(;iter != data.end();++iter) { if(leastNumbers.size() < k) leastNumbers.insert(*iter); else { setIterator iterGreatest = leastNumbers.begin(); if(*iter < *iterGreatest) { leastNumbers.erase(*iterGreatest); leastNumbers.insert(*iter); } } } }
很多时候不是我们做不好,而是没有竭尽全力......
分类:
【微软面试100题】
posted on 2014-10-27 10:11 tractorman 阅读(235) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?