剑指offer-63.数据流中的中位数-python

63.数据流中的中位数

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

记录

方法一:
排序

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.arr=[]
    def Insert(self, num):
        self.arr.append(num)
        self.arr.sort()
    def GetMedian(self,sb):
        length=len(self.arr)
        return self.arr[length//2] if length%2==1 else (self.arr[length//2]+self.arr[length//2-1])/2.0
有个bug:def GetMedian(self,sb):自己添加一个参数

方法二:
最大堆和最小堆
python中的堆
heapq模块
代码来源:代码(明白意思但是不知道怎么写)

# -*- coding:utf-8 -*-
from heapq import *
class Solution:
    def __init__ (self):
        self.maxheap = []
        self.minheap = []
    def Insert(self, num):
        if (len(self.maxheap)+len(self.minheap))&1: #当前两个堆的总数为奇数
            if len(self.minheap)> 0:  
                if num > self.minheap[0]:#大于最小堆的数
                    heappush(self.minheap, num)#新数据插入最小堆
                    heappush(self.maxheap, -self.minheap[0])#最小堆中的最小插入最大堆
                    heappop(self.minheap)
                else:
                    heappush(self.maxheap, -num)
            else:
                heappush(self.maxheap, -num)
        else:                           #当前两个堆的总数为偶数 
            if len(self.maxheap)> 0: #小于最大堆里的元素
                if num < -self.maxheap[0]:
                    heappush(self.maxheap, -num)#新数据插入最大堆
                    heappush(self.minheap, -self.maxheap[0])#最大堆中的最大元素插入最小堆
                    heappop(self.maxheap)
                else:
                    heappush(self.minheap, num)
            else:
                heappush(self.minheap, num)
        #print (self.minheap)
    def GetMedian(self,n=None):
        if (len(self.maxheap)+len(self.minheap))&1:
            mid = self.minheap[0]
        else:
            mid = (self.minheap[0]+self.maxheap[0])/2.0
        return mid

在这里插入图片描述
这种题还是不适合用python:
java:

import java.util.*;
public class Solution {
    private int count = 0;
    private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    private PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1,o2)->o2-o1);
    public void Insert(Integer num) {
        if(count % 2 == 0){
            //当数据总数为偶数时,新加入的元素,应当进入小根堆
            //不是直接进入小根堆,而是经大根堆筛选后取大根堆中最大元素进入小根堆
             //新加入的元素先入到大根堆,由大根堆筛选出堆中最大的元素
            maxHeap.offer(num);
            minHeap.offer(maxHeap.poll());
        }
        else{
            //当数据总数为奇数时,新加入的元素,应当进入大根堆
            //注意不是直接进入大根堆,而是经小根堆筛选后取小根堆中最大元素进入大根堆
            //新加入的元素先入到小根堆,由小根堆筛选出堆中最小的元素
            minHeap.offer(num);
            maxHeap.offer(minHeap.poll());
        }
        count++;
    }

    public Double GetMedian() {
        if(count % 2 == 0){//如果是偶数个数  就把小顶堆的根元素和大顶堆的根元素 拿出
            return (minHeap.peek() + maxHeap.peek())/2.0;
        }
        else{//如果是奇数个数 那说明中位数就在小顶堆的根的位置
            return minHeap.peek()/1.0;
        }
    }
}

代码源地址

C++:

class Solution {
public:
     vector<int> max;
     vector<int> min;
    void Insert(int num)
    {  
        if((max.size()&1)==0)//偶数时 ,放入最小堆
        {
            if(max.size()>0&&num<max[0])//偶数插入小顶堆
            {
                // push_heap (_First, _Last),要先在容器中加入数据,再调用push_heap ()
                max.push_back(num);//先将元素压入容器
                //push_heap()是向堆中插入一个元素,并且使堆的规则依然成立
                push_heap(max.begin(),max.end(),less<int>());//调整最大堆
                num=max[0];//取出最大堆的最大值
                //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据
                pop_heap(max.begin(),max.end(),less<int>());//把最大堆的堆顶值和最后一个元素交换,删除最大堆的最大值
                max.pop_back();//在容器中删除
            }
            min.push_back(num);//压入最小堆
            push_heap(min.begin(),min.end(),greater<int>());//调整最小堆
        }
        else{//奇数时候,放入最大堆
            if(min.size()>0&&num>min[0])
            {
                min.push_back(num);//先压入最小堆
                push_heap(min.begin(),min.end(),greater<int>());//调整最小堆
                num=min[0];//得到最小堆的最小值(堆顶)
                 //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据
                pop_heap(min.begin(),min.end(),greater<int>());//删除最小堆的最大值
                min.pop_back();//在容器中删除
            }
            max.push_back(num); // 压入数字
            push_heap(max.begin(),max.end(),less<int>());//调整最大堆
        }
    }
 
    double GetMedian()//获取中位数
    { 
        if(max.si***.size()<=0) return 0;//没有元素,抛出异常   
      //偶数,取平均        
 //奇数,取最小堆,因为最小堆数据保持和最大堆一样多,或者比最大堆多1个   
        return ((max.si***.size()&1)==0)?(max[0]+min[0])/2.0:min[0];
     
    }
 
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值