难度:困难
一、题目描述:
二、解题分析:
1、
使用大根堆和小根堆
假想我们现在有两个容器 A, B 这两个容器将我们的整体数据分成两部分,且 A 中的数据都小于 B 中的数据,并且 A 中的最后一个数据是 A 里面最大的
B 的第一个数据是 B 中最小的.
好了 我们有了上面的条件,那我们怎么找到中位数呢?
当整体数目为奇数时,中间的那个数就是所求.当整体数目为偶数时,中间两个数的和再除以 2 ,就能得到结果
但这和我们上面的两个容器有什么关系呢?
我们只要将上面的两个容器的数据数目只差保持在 1 之内即可,也就是说 A 和 B 将整体数据以中位数划分开来了
#python2
class MedianFinder(object):
from heapq import *
def __init__(self):
"""
initialize your data structure here.
"""
self.bigHpeap = []
self.smallHeap = []
def addNum(self, num):
"""
:type num: int
:rtype: None
"""
if len(self.bigHpeap) == len(self.smallHeap):#总数为偶数时,先插入到大根堆,在插入到小根堆
heapq.heappush(self.smallHeap, -heapq.heappushpop(self.bigHpeap, -num))
else:#总数为奇数时,先插入到小根堆,在插入到大根堆
heapq.heappush(self.bigHpeap, -heapq.heappushpop(self.smallHeap, num))
def findMedian(self):
"""
:rtype: float
"""
if len(self.bigHpeap) == len(self.smallHeap):
return (-self.bigHpeap[0] + self.smallHeap[0]) / 2.0
else:
return self.smallHeap[0]
# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()
2、
此处撰写解题思路
主要思路:维护一个大根堆和一个小根堆,保证每一时刻操作完后,两个堆中的元素个数差异不超过1,
1)若当前元素个数相等,则将当前的要插入的数insert到其中一个堆(如大根堆)中,再从该堆(大根堆)中弹出堆顶元素到另一个堆(小根堆)中;
2)若当前元素个数不等,也就是小根堆比大根堆多1个元素,则将当前的要插入的数insert到小根堆中,再从该堆(小根堆)中弹出堆顶元素到另一个堆(大根堆)中。
也就是说,保证任意时刻大根堆中所有元素都小于小根堆的堆顶元素,大根堆存储排序后大小占前N/2个数,小根堆存储后N/2个数,中位数就是对应的堆顶元素(如果从数据流中读出奇数个数值,那么中位数就是比另一个数要多一个数的那个堆(这里是小根堆)。如果从数据流中读出偶数个数值,那么中位数就是堆顶两个数的平均值)。
#python3
class SmallRootHeap:
def __init__(self):
self.arr = list()
def get_length(self):
return len(self.arr)
def heap_insert(self,num):
heapq.heappush(self.arr, num)
def heapify(self):
heapq.heapify(self.arr)
def heap_pop(self):
return heapq.heappop(self.arr)
def get_top(self):
if not self.arr:return
return self.arr[0]
class LargeRootHeap:
def __init__(self):
self.arr = list()
def get_length(self):
return len(self.arr)
def heap_insert(self,num):
heapq.heappush(self.arr,-num)
def heap_pop(self):
return -heapq.heappop(self.arr)
def heapify(self):
heapq.heapify(self.arr)
def get_top(self):
if not self.arr:return
return -self.arr[0]
class MedianFinder:
def __init__(self):
self.smallrootheap, self.largerootheap = SmallRootHeap(),LargeRootHeap()
def addNum(self,num:int) -> None:
if self.smallrootheap.get_length() == self.largerootheap.get_length():
self.largerootheap.heap_insert(num)
self.smallrootheap.heap_insert(self.largerootheap.heap_pop())
else:
self.smallrootheap.heap_insert(num)
self.largerootheap.heap_insert(self.smallrootheap.heap_pop())
def findMedian(self) -> float:
if self.largerootheap.get_length() == self.smallrootheap.get_length():
return (self.largerootheap.get_top() + self.smallrootheap.get_top())/2
else:
return self.smallrootheap.get_top()
# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()