【剑指Offer】最小的k个数---大顶堆 Java

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

求数组中最小(最大)的n个数通常可以使用大顶堆(小顶堆)的方法来是实现。大顶堆容易获取到堆中最大的数,若当前数比堆顶大,则可以直接舍去,因此更便于维护。小顶堆则相反,适用于求取前n大的数。

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if(k==0)return new int[0];
        if(k==arr.length)return arr;
        int[] res=new int[k];//复制前k个数,作为大顶堆的数组初始化。
        for(int i=0;i<k;i++){
            res[i]=arr[i];
        }
        build(res);//构建大顶堆
        //第k个数之后的数依次与堆顶比较;若比堆顶大则直接排除;若比堆顶小则替换当前堆顶,并维护堆。
        for(int i=k;i<arr.length;i++){
            if(arr[i]<res[0]){
                res[0]=arr[i];
                maintain(res,0);
            }
        }
        return res;
    }
    public void build(int[] res){//建大顶堆;将大顶堆用数组的形式表示。
    //父节点索引(i-1)/2;左子索引2*i+1;右子索引2*i+2。
        int last=(res.length-1)/2;//找出最后一个父节点的位置
        while(last>=0){
             maintain(res,last--);//对每个父节点进行维护,直到堆顶。
        }
       
    }
    public void maintain(int[] res,int l){
        if(l>=res.length)return;
        int c1=2*l+1;//左子节点索引
        int c2=2*l+2;//右子节点索引
        int max=l;//初始化max为根节点
        if(c1<res.length&&res[c1]>res[max])
            max=c1;
        if(c2<res.length&&res[c2]>res[max])
            max=c2;
        if(max!=l){//若父节点不是三个节点中最大的,则换位。
            int temp=res[l];
            res[l]=res[max];
            res[max]=temp;
            maintain(res,max);//维护新换父节点的子树
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值