大小根堆和java中双优先队列的应用

本文介绍如何利用小根堆和大根堆解决京东笔试题中的中位数求和问题。通过动态维护两个堆,可以在O(log n)的时间复杂度内找到任意子序列的中位数,并计算所有子序列的中位数之和。

小根堆和大根堆

完全二叉树

完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。

满二叉树

除了叶子节点外,每个节点的两个子节点都全的二叉树。

小根堆

首先小根堆是一个完全二叉树,并且任何子树的最小值是它的根节点。

大根堆

同理,大根堆也是一个完全二叉树,并且任何子树的最大值是它的根节点。

应用

问题

京东笔试题
第一行一个数字n,表示序列nums的长度,之后一行一个长度为n序列,每个数字用空格分割,求所有子序列的中位数之和。
我们可以用一个大根堆和一个小根堆动态的寻找中位数,每次寻找中位数的复杂度为O(longn)。

用大小根堆解题

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n=Integer.parseInt(in.nextLine());
        String[] sarr=in.nextLine().split(" ");
        int[] arr=new int[sarr.length];
        for(int i=0;i<arr.length;i++){
            arr[i]=Integer.parseInt(sarr[i]);
        }
        long re=0;
        for(int i=0;i<arr.length;i++){
            PriorityQueue<Integer> queue_min =
                    new PriorityQueue<Integer>((o1,o2) -> o1 - o2);
            PriorityQueue<Integer> queue_max =
                    new PriorityQueue<Integer>((o1,o2) -> o2 - o1);
            int flag=arr[i];
            re+=flag;
            for(int j=i+1;j<arr.length;j++){
                //System.out.println(re);
                if(flag>arr[j]){
                    if(queue_max.size()<=queue_min.size()){
                        queue_max.add(flag);
                        flag=arr[j];
                        re+=flag;
                    }
                    else if(queue_max.size()>queue_min.size()){
                        queue_min.add(arr[j]);
                        re+=flag;
                    }
                }
                else{
                    if(queue_max.size()>=queue_min.size()){
                        queue_min.add(arr[j]);
                        re+=flag;
                    }
                    else if(queue_max.size()<queue_min.size()){
                        queue_max.add(flag);
                        flag=arr[j];
                        re+=flag;
                    }
                }
            }
            //System.out.println(re);
            //System.out.println("================");
        }
        System.out.println(re);
    }


}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值