输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
这道题很经典,可以总结为求TOPK问题。
解决方法主要有三个。
方法一. 直接排序方法
调用Java的排序方法进行排序,速度居中,代码简单。
public static int[] getLeastNumbers3(int[] arr, int k) {
if(k==0){
return new int[]{};
}
if(k>=arr.length){
return arr;
}
Arrays.sort(arr);
int[] res=new int[k];
for(int i=0;i<k;i++){
res[i]=arr[i];
}
return res;
}
方法二 堆排序方法
求TOPK问题的典型思路是采用大根堆(找较小数)或者小根堆(找较大数),速度是最慢的,但是在一些特殊问题中采用堆排序思想能够帮助我们解决。
public static int[] getLeastNumbers2(int[] arr, int k) {
if(k==0){
return new int[]{};
}
if(k>=arr.length){
return arr;
}
PriorityQueue<Integer> heap=new PriorityQueue<>(((o1, o2) ->o2-o1 ));
for(int i=0;i<arr.length;i++){
heap.add(arr[i]);
}
int[] res=new int[k];
for(int i=0;i<k;i++){
res[i]=heap.poll();
}
return res;
}
方法三 快速排序
采用快排的思想进行数组分割,能够有效减少排序次数,最终不需要完成所有排序,只需要满足给定数量即可。是最快的一种方法。
public static int[] getLeastNumbers4(int[] arr, int k) {
if(k==0||arr.length==0){
return new int[0];
}
if(k>=arr.length){
return arr;
}
quickSort(arr,0,arr.length-1,k);
int[] res=new int[k];
for(int i=0;i<k;i++){
res[i]=arr[i];
}
return res;
}
public static void quickSort(int[] arr, int begin, int end, int k){
int i=begin;
int j=end;
int flag=arr[begin];
while(i<j){
while(i<j&&arr[j]>=flag){
j--;
}
while(i<j&&arr[i]<=flag){
i++;
}
arr[i]=arr[j]^arr[i]^(arr[j]=arr[i]);
}
arr[i]=arr[begin]^arr[i]^(arr[begin]=arr[i]);
if(i-begin+1<k){
quickSort(arr,i+1,end,k-(i-begin+1));
}
if(i-begin+1>k){
quickSort(arr,begin,i-1,k);
}
}
同学好多都毕业了,而我还在等待,学习学习学习,懒惰懒惰懒惰,每天都在立志向上和自暴自弃中挣扎,未来究竟如何呢?