剑指 Offer 41. 数据流中的中位数

剑指 Offer 41. 数据流中的中位数

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

在这里插入图片描述

解答
class MedianFinder {
    
    /**
    解题思路:给定一长度为N的无序数组,其中位数的计算方法:首先对数组执行排序(使用O(NlogN)时间),
              然后返回中间元素即可(使用O(1)时间)

              结果超出时间限制
     */

    /** initialize your data structure here. */
    /*
    LinkedList<Integer> ll = null;
    public MedianFinder() {
        ll = new LinkedList<Integer>();
    }
    */
    
      /**
      折半插入
        使用二分查找找到应该插入的位置
        当low > high时折半查找停止,如果此时low <= ll.size()-1,应将[low,ll.size()-1]的元素全部后移,并将num复制到low所指位置
        当ll.get(mid) == num,为了保证算法的”稳定性“,应继续在mid所指位置右边寻找插入位置
        当low > high时折半查找停止,如果此时 low >= ll.size,则将num复制到low所指的位置
    
     */
     /*
    public void addNum(int num) {
        int low,high,mid;
       low = 0;
       high = ll.size() - 1;
       while(low <= high){
           mid = (low + high) / 2;
           if(ll.get(mid) > num){
               high = mid - 1;
           }else{
               low = mid + 1;
           }
       }
       if(low <= ll.size()-1){
           
           ll.add(num);
           int j = ll.size()-1;
           while(j > low){
               ll.set(j,ll.get(j-1));
               j--;
           }
           ll.set(j,num);
       }else{
           ll.add(num);
       }
       for(Integer i:ll){
            System.out.print(i + " ");
        }
        System.out.println();
    }
    
    public double findMedian() {
        
       
        int length = ll.size();
        int mid  = length / 2;
        if(length%2 != 0){
            return ll.get(mid);
        }else{
            return (ll.get(mid) + ll.get(mid-1))/2.0;
        }
    }

    */
    /**
    解题思路:
        建立一个 小顶堆A 和 大顶堆B,各保存列表的一半元素,且规定:
            A保存 较大 的一半,长度为N/2(N为偶数)或(N+1)/2(N为奇数)
            B保存 较小 的一半,长度为N/2(N为偶数)或(N-1)/2(N为奇数)
        随后,中位数可仅根据A,B的堆顶元素计算得到
    算法流程:
        设元素总数为N = m + n,其中m和n分别为A和B中的元素个数
        addNum(num):
            当m = n(即N为偶数):需向A添加元素。实现方法:将新元素num插入至B,在将B堆顶元素插入至A
            当m ≠ n(即N为奇数):需向B添加元素。实现方法:将新元素num插入至A,再将A堆顶元素插入至B
        findMedian()函数:
            当 m = n:中位数为A 和 B的堆顶元素之和除以2
            当 m ≠ n:中位数为A的堆顶元素
     */
    
    /** initialize your data structure here. */
    PriorityQueue<Integer> minHeap = null;
    PriorityQueue<Integer> maxHeap = null;
    public MedianFinder() {
        minHeap = new PriorityQueue(new Comparator<Integer>(){
            public int compare(Integer a,Integer b){
                return a - b;
            }
        });

        maxHeap = new PriorityQueue(new Comparator<Integer>(){
            public int compare(Integer a,Integer b){
                return b - a;
            }
        });
        
    }

    public void addNum(int num) {

        if(minHeap.size() == maxHeap.size()){
            maxHeap.offer(num);
            minHeap.offer(maxHeap.poll());
        }else{
            minHeap.offer(num);
            maxHeap.offer(minHeap.poll());
        }
    
    }
    
    public double findMedian() {
        if(minHeap.size() == maxHeap.size()){
            return (minHeap.peek() + maxHeap.peek()) / 2.0;
        }else{
            return minHeap.peek();
        }
    }

}

/**
 * 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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值