发布于 2021-09-07 11:30 ,所属分类:2021面试经验技巧分享
今天是我坚持写题解的第 30 天!
设计一个算法,找出数组中最小的 k 个数。以任意顺序返回这 k 个数均可。
k
示例:
输入:arr = [1,3,5,7,2,4,6,8], k = 4输出:[1,2,3,4]
输入:arr = [1,3,5,7,2,4,6,8], k = 4
输出:[1,2,3,4]
提示:
0 <= len(arr) <= 1000000 <= k <= min(100000, len(arr))
链接:https://leetcode-cn.com/problems/smallest-k-lcci
这道题最简单的方法,排个序返回前 k 个元素即可。
代码如下:
classSolution{publicint[]smallestK(int[]arr,intk){Arrays.sort(arr);int[]ans=newint[k];System.arraycopy(arr,0,ans,0,k);returnans;}}
我们可以使用大顶堆维护最小的 k 个元素,顶堆是这 k 个元素的最大值,每次来一个新的元素,如果它比堆顶元素小,说明它可以替换掉堆顶元素成为最小的 k 个元素,即把堆顶元素弹出并把这个元素入堆。
使用大顶堆的好处是,我们可以很方便的查询到最小的这 k 个元素中的最大值,每次使用这个最大值与新元素比较即可。
classSolution{publicint[]smallestK(int[]arr,intk){int[]ans=newint[k];if(arr.length==0||k==0){returnans;}//大顶堆PriorityQueue<Integer>heap=newPriorityQueue<>((a,b)->b-a);for(intnum:arr){//堆元素数量不满k,直接入堆if(heap.size()<k){heap.offer(num);}elseif(num<heap.peek()){//新元素比堆顶元素小,弹出堆顶并让新元素入堆heap.poll();heap.offer(num);}}//遍历完所有元素,堆中的元素即为最小的k个元素for(inti=0;i<k;i++){ans[i]=heap.poll();}returnans;}}
仔细分析这道题目,只是要求我们返回最小的 k 个元素,但是,并不需要把它们排好序,所以,我们可以使用快排的思想来操作。
比如,给定 arr=[1,3,5,7,2,4,6,8], k=4,我们只要找到一个 轴 使得它左边的元素正好等于 k 个,那么,左边的元素都是比这个 轴 小的,也就是符合最小的 k 个元素的。
arr=[1,3,5,7,2,4,6,8], k=4
比如,我们在某一次递归时,找到的轴正好是 5,那么数组可能变成了 [1,3,2,4,5,7,6,8],这时,左边的元素数量正好等于 4 个,所以,这时候直接返回就可以了。
[1,3,2,4,5,7,6,8]
另外,考虑 k=5 的时候,如果上面找到的轴也是 5,也是可以返回的,因为 5 及其左边的所有元素都比 5 右边的元素小,这一块请仔细体会下。
k=5
请看代码:
classSolution{publicint[]smallestK(int[]arr,intk){int[]ans=newint[k];if(arr.length==0||k==0){returnans;}quickSort(arr,0,arr.length-1,k);System.arraycopy(arr,0,ans,0,k);returnans;}privatevoidquickSort(int[]arr,intleft,intright,intk){if(left>=right){return;}//为了防止快排退化成O(n^2)使用随机位置的元素为轴intrand=ThreadLocalRandom.current().nextInt(right-left+1)+left;swap(arr,left,rand);intpivot=arr[left];inti=left,j=right;while(i<j){while(i<j&&arr[j]>pivot){j--;}while(i<j&&arr[i]<pivot){i++;}if(arr[i]==arr[j]&&i<j){i++;}else{swap(arr,i,j);}}//上面循环结束后i和j是相等的,即轴的新位置//如果轴的位置等于k或者k-1,直接返回if(i==k-1||i==k){return;}//如果轴的位置比k大,则需要对左边的元素重新操作,否则对右边的元素重新操作if(i>k){quickSort(arr,left,i-1,k);}else{quickSort(arr,i+1,right,k);}}privatevoidswap(int[]arr,inti,intj){inttmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}}
如果对你有帮助,请点个赞吧,谢谢^^
也可以我的公号【彤哥来刷题啦】,每日分享题解,一起刷题,一起拿全家桶。
孙路弘小升初备战数学每天一题100天100讲视频课程+讲义
尚硅谷Java面试题第一季 .
[就业指导] 2017最新IOS面试必看题教程 尚学堂 iOS面试题 视频教程 教学视频
[JAVA面试题] 传智博客Java就业班面试资料java面试题(程序猿面试技巧+常见笔试题分析) 六讲
大米快学阅读快乐学习英语
[就业指导] Java面试题专属视频 最新Java阿里京东美团滴滴java面试题及答案教程
Java面试题视频找工作不用愁
JAVA面试题] 极客JavaWeb工程师全套视频教程 (初级+中级+高级) 一共485集 送面试辅导
java基础面试题精选(包含答案)
Java高薪就业面试题视频找工作不用愁
[JAVA面试题] Java BAT大型公司面试专属必备技能视频教程
[就业指导] Java面试题视频找工作不用愁
小品mp3全,快怀大笑∵
Java面试专属视频 最新Java阿里京东美团滴滴面试题及答案教程
最新热门项目萌娃搞笑段子:自带流量涨粉快!3分钟一条视频
2018最新系统CSS样式布局与面试题高级教程
[就业指导] Java面试专属视频 最新Java阿里京东美团滴滴面试题及答案教程
[java面试题] 尚硅谷1024程序员福利之java学科新增面试宝典视频教程
各知名互联网公司的前端面试题来了!
河北衡水中学2020届全国高三第一次联合考试历史试题及答案
前端面试教程将近6小时典型前端面试题实战精讲
【绝密补单学习】店铺快年度学员,精讲干货直接操作,不容错过!
Java教程_面试题破解之银行业务调度系统教程
相关资源