剑指offer_29:最小的k个数

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]

限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000

1、直接排序

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] res=new int[k];
        Arrays.sort(arr);
        for(int i=0;i<k;i++){
            res[i]=arr[i];
        }
        return res;
    }
}

2、快速选择(快排思想)

快排就是在把元素分为两类,一边比基准小,一边比基准大,这道题只需要选择一侧的数据就行

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if(k==0){
            return new int[0];
        }else if(arr.length<=k){
            return arr;
        }
        part(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 void part(int[] a,int left,int right,int k){
        int num=quickSort(a,left,right);//获取分界值
        if(num==k){
            return;
        }else if(num>k){//缩小范围
            part(a,left,num-1,k);
        }else{
            part(a,num+1,right,k);
        }
    }
    public int quickSort(int[] a,int left,int right){
        int i=left;
        int j=right+1;
        int v=a[left];//a[left]作为分界点
        while(true){
            while(a[++i]<v){//向右找比分界点大的值
                if(i==right){//直到范围的最右边
                    break;
                }
            }
            while(a[--j]>v){//向左找比分界点小的值
                if(j==left){//直到范围的最左边
                    break;
                }
            }
            if(i>=j){//相遇退出
                break;
            }
            swap(a,i,j);//未相遇,交换
        }
        swap(a,left,j);//将分界点放在正确的位置,只能用j,不能用i。例子:0 1 2 1
        return j;
    }
    public void swap(int[] a,int x,int y){
        int t=a[x];
        a[x]=a[y];
        a[y]=t;
    }
}

3、堆排序

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if(k==0){
            return new int[0];
        }else if(arr.length<=k){
            return arr;
        }
        Queue<Integer> heap=new PriorityQueue<>((v1,v2)->v2-v1);
        for(int i:arr){
            if(heap.size()<k){
                heap.offer(i);
            }else if(heap.peek()>i){
                heap.poll();
                heap.offer(i);
            }
        }
        int[] res=new int[heap.size()];
        int index=0;
        for(int i:heap){
            res[index++]=i;
        }
        return res;
    }
}
posted @ 2021-02-18 10:33  小昊子丫  阅读(37)  评论(0编辑  收藏  举报