难度:中等
题目:
设计一个算法,找出数组中最小的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
}
}
}
运行结果:
系列持续更新中,喜欢练习算法的那就点个攒吧