剑指 Offer 40. 最小的k个数
快速排序
因为不要求返回数组的顺序,所以可以不做完整的排序
(做完整的快速排序)
完整快排递归版:(在一个函数里实现了快排,而不是像邓书里面那样写成两个)
class Solution {
//快速排序
//快速选择
//堆排序和快速排序的比较--面试热点
public int[] getLeastNumbers(int[] arr, int k) {
quickSort(arr,0,arr.length-1);
return Arrays.copyOf(arr,k);//这个copyOf第一次用
}
void quickSort(int[] arr,int lo,int hi){//[lo,hi]内处理
if(lo>=hi)return;//或者lo>=hi
int i=lo,j=hi;//存起来,递归要用
int pivot=arr[lo];//默认轴点,首元素
while(lo<hi){
while(lo<hi&&arr[hi]>=pivot)hi--;
arr[lo]=arr[hi];//退出上述循环时,hi指向的元素是小于轴点的,应在轴点左侧
while(lo<hi&&arr[lo]<=pivot)lo++;
arr[hi]=arr[lo];//退出上述循环时,lo指向的元素是大于轴点的,应在轴点右侧
}//退出循环时,lo==hi,轴点位置找到了
arr[lo]=pivot;
//递归处理前缀和后缀
quickSort(arr,i,lo-1);
quickSort(arr,lo+1,j);
}
}
(不做完整的快排)
选择区间进行递归
唯一的区别和注意事项在代码注释中
class Solution {
//快速排序
//快速选择
//堆排序和快速排序的比较--面试热点
public int[] getLeastNumbers(int[] arr, int k) {
quickSort(arr,k,0,arr.length-1);
return Arrays.copyOf(arr,k);//这个copyOf第一次用
}
void quickSort(int[] arr,int k,int lo,int hi){//[lo,hi]内处理
if(lo>hi)return;//如果是lo==hi会报错,报栈溢出
int i=lo,j=hi;//存起来,递归要用
int pivot=arr[lo];//默认轴点,首元素
while(lo<hi){
while(lo<hi&&arr[hi]>=pivot)hi--;
arr[lo]=arr[hi];//退出上述循环时,hi指向的元素是小于轴点的,应在轴点左侧
while(lo<hi&&arr[lo]<=pivot)lo++;
arr[hi]=arr[lo];//退出上述循环时,lo指向的元素是大于轴点的,应在轴点右侧
}//退出循环时,lo==hi,轴点位置找到了
arr[lo]=pivot;
//递归处理前缀和后缀
if(lo>k)quickSort(arr,k,i,lo-1);//这两个条件别搞混了
if(lo<k)quickSort(arr,k,lo+1,j);//与做完整递归相比只加了这两个判断
}
}
堆:
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if(k==0) return new int[0];
PriorityQueue<Integer> que=new PriorityQueue<>((x,y)->(y-x));//申请一个大顶堆
for(int i=0;i<arr.length;i++){
if(que.size()<k){
que.offer(arr[i]);
}
else{
if(que.peek()>arr[i]){
que.poll();
que.offer(arr[i]);
}
}
}
int[] ans=new int[que.size()];
for(int i=0;i<ans.length;i++){
ans[i]=que.poll();
}
return ans;
}
}

浙公网安备 33010602011771号