利用堆的结构的题目

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if (k == 0 || arr.length == 0) {
            return new int[0];
        }
        Queue<Integer> maxHeap=new PriorityQueue<>((v1,v2)->v2-v1);
        for(int num: arr){
            if(maxHeap.size()<k){
               maxHeap.offer(num);
            }else if(num<maxHeap.peek()){
               maxHeap.poll();
               maxHeap.offer(num);
            }
        }
        int []res=new int [maxHeap.size()];
        int id=0;
        for(int num : maxHeap){
            res[id++]=num;
        }
        return res;
    }
}

剑指 Offer 45. 把数组排成最小的数

  •  利用最小堆来,其最重要的核心就是关于 a+b<b+a这种思想,比如 1+2<2+1这种思想
class Solution {
    public String minNumber(int[] nums) {
        PriorityQueue<String> minHeap=new PriorityQueue<>((a,b)->{
            return new String(a+b).compareTo(b+a);
        });
        for(int i:nums){
            minHeap.add(String.valueOf(i));
        }
        StringBuilder res=new StringBuilder();
        while(!minHeap.isEmpty()){
            res.append(minHeap.poll());
        }
        return res.toString();
    }
}

 

  • 用大顶堆+小顶堆方法,可以看作大顶堆是普通班,小顶堆是实验班。数量上时刻保持 小顶-大顶<=1(两堆相等或者小顶比大顶多一个)而且实验班的学生成绩都大于普通班。
  • 新学生先入普通班(大顶堆),此时可能会失去平衡了,于是取大顶堆的第一个(班里最好的学生)加入实验班(小顶堆),判断若数量过多(不是等于或多一个),取第一个(实验班里最差的学生)到普通班(大顶堆)里。 取中位数的时候,若两堆数量相等,则各取堆顶取平均,若小顶比大顶多一,则多的那一个就是中位数。

 

class MedianFinder {
    PriorityQueue <Integer> large;//大根堆
    //大根堆中的元素都是小于小根堆的
    PriorityQueue <Integer> small;//小根堆
    //小根堆的元素都是大于大根堆的
    /** initialize your data structure here. */
    public MedianFinder() {
        large=new PriorityQueue<>((n1,n2)->{
            return n2-n1;
        });
        small=new PriorityQueue<>();
    }
    
    public void addNum(int num) {
        //保证两个堆的元素一样,我们就只需要比较两个堆的元素个数
        //如何保证小根堆的元素都大于大根堆
        //首先把新的数据先放入到大根堆
        //然后把大根堆的最大数放到小根堆 //保证小根堆的数都大于大根堆
        //如果我们的小根堆的数量比大根堆多的不止一个
        //那么就将小根堆的最小值放到大根堆 来保证平衡
         large.add(num);
         small.add(large.poll());
         if(large.size()+1<small.size()){
             large.add(small.poll());
         }
    }
    
    public double findMedian() {
        //我们的思想就是 来保证两个堆的数量是相同的(如果是奇数个元素,一个堆会比;另一个堆多一个数)
        //然后大根堆中的数都是小于小根堆中的数的
        //也就是大根堆的最大数小于小根堆的最小数
        //那么我们的中位数就是 如果是奇数个元素,就是多一个元素的那个数,如果是偶数,就是两个堆的
        //堆顶元素的平均数
        if(small.size()>large.size()){
            return small.peek();
        }
        return (double)(large.peek()+small.peek())/2;
    }
}

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

库里不会投三分

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值