难度:中等
题目:
设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4]
提示:
0 <= len(arr) <= 100000
0 <= k <= min(100000, len(arr))
Related Topics
- 数组
- 分治
- 快速选择
- 排序
- 堆(优先队列)
重点!!!解题思路
第一步:
明确解题手段:此题比较简单的做法就是使用堆来解决,但是此章节我们练习的是排序算法,即此题我们采用排序算法来解决
第二步:
还是像排序算法 中使用模仿STL的快速排序思想,这里面我们就不需要使用插入排序了,直接使用手写的根据基准值快排即可(分区思想)
第三步:
分区之后,我们判断分区的大小和K的大小,不够或者超出就重新进行递归求解,正好相等那就返回结果
源码+讲解:
class Solution {public int[] smallestK(int[] arr, int k) {int[] ans=new int[k]; //创建一个结果集if (k==0) return ans;quick_sort(arr,0,arr.length-1,k); //k不为0就进行递归求解for (int i=0;i<k;i++){ //将原数组的拷贝到结果集中ans[i]=arr[i];}return ans;}public int getmid(int a,int b,int c){ //取基准值int max=Math.max(a,Math.max(b,c));int min=Math.min(a,Math.max(b,c));if (a!=max && a!=min) return a;if (b!=max && b!=min) return b;return c;}public void swap(int[] arr,int i,int j){ 交换数组值int t=arr[i];arr[i]=arr[j];arr[j]=t;}public void quick_sort(int[] arr,int l,int r,int k){if (l>=r) return; //边界范围int i=l,j=r,m=getmid(arr[i],arr[j],arr[(i+j)/2]); //拷贝边界+取基准值do {while (arr[i]<m) i++;while (arr[j]>m) j--;if (i<=j){ //此时arr[i]>arr[j] 要进行交换swap(arr,i,j);i++; //交换后都进行移动j--;}}while (i<=j); //边界范围if (j-l==k-1) return; //j是已排序好的右边界 j-l为已排序号的数组大小if (j-l>=k){quick_sort(arr,l,j,k); //超出即再从已知范围继续寻找k个数}else {quick_sort(arr,i,r,k-i+l); //少了就从i开始到数组结尾找k-(j-l)-1个数,化简j+1=r 即最后化简为k-i+1}}}
运行结果:
系列持续更新中,喜欢练习算法的那就点个攒吧