寻找无序数组的中位数(Java)

1、概念

以下摘自百度百科:对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,通常取最中间的两个数值的平均数作为中位数。

由概念可得,对于一个有小到大排序好的数据集,若其长度是n,n为奇数,则中位数就是n/2下标的位置。如果数据集的长度是n,n为偶数,则中位数就是n/2与n/2+1下标的位置的平均值。

获取中位数的主要时间复杂度,由排序算法的时间复杂度决定,最快为nLog(n)。

2、优化解法

首先将数据集的个数分成奇数和偶数两种情况进行探讨,同时发现这两种情况有共同点,如下图所示。数据集数据长度为2n+1或2n时,我们只需要把最大n+1构建成一个新的Collection,再根据奇偶情况计算中位数即可。

而JDK恰巧有这样的数据结构:PriorityQueue(优先队列),其通过完全二叉树实现的小顶堆,插入数据的时间复杂度为Log(n),并且堆顶是最小元素。

Java实现如下:

public class Math {
    /**
     * 获取中位数
     * @param arr
     * @return
     */
    public Double getMedianNum(int[] arr){
        //边界值
        if(arr == null || arr.length == 0){
            return null;
        }

        //考虑到arr长度为1时交由下面业务逻辑处理耗时也耗空间,此处做提前判断时间复杂度也才多O(1)
        if(arr.length == 1){
            return (double) arr[0];
        }
        
        // 默认是小顶堆,大顶堆为new PriorityQueue<>(Collections.reverseOrder())
        PriorityQueue<Integer> minPQ = new PriorityQueue<>();
        int length = arr.length;
        int k = length/2+1;

        for(int i = 0;i<k;i++){
            minPQ.add(arr[i]);
        }
        for(int i = k;i<length;i++){
            if(minPQ.peek() < arr[i]){
                minPQ.poll();
                minPQ.add(arr[i]);
            }
        }
        if (length % 2 == 0){
            return (minPQ.poll() + minPQ.peek())/ 2.0;
        } else{
            return minPQ.peek().doubleValue();
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值