数据流中的中位数
本题利用堆排序思想。
首先,使用最大堆和最小堆,保证最大堆的数<最小堆的数。
每次插入和取出都需要调整堆。保持两个堆一样的结点数目,或者最小堆的结点数比最大堆多1。
建堆:
如果已经两个堆结点数目相同,放到最小堆,但如果该数小于最大堆,说明该数应该放到最大堆,插入最大堆之后取最大堆的堆顶插入到最小堆;
如果已经两个堆结点数目不同,即最大堆的数少,应该放到最大堆,但如果该数大于最小堆,说明应该放到最小堆,插入最小堆之后取最小堆的最小值插入到最大堆;
取出中位数:
如果总数为奇数个,取最小堆堆顶;
如果总数为偶数个,取两个堆顶平均值。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.n = 0
self.larger_heap = []
self.smaller_heap = []
# 最大堆插入操作:
def larger_heap_push(self, num):
self.larger_heap.append(num)
n = len(self.larger_heap)
i = n - 1
while i > 0:
if self.larger_heap[i] > self.larger_heap[(i-1)//2]:
self.larger_heap[i], self.larger_heap[(i-1)//2] = self.larger_heap[(i-1)//2], self.larger_heap[i]
i = (i-1)//2
else:
break
# 最大堆取出堆顶后调整堆:
def larger_heap_pop(self):
ans = self.larger_heap[0]
self.larger_heap[0] = self.larger_heap.pop()
n = len(self.larger_heap)
i = 0
while 2 * i + 1 < n:
son = 2 * i + 1
if son + 1 < n and self.larger_heap[son+1] > self.larger_heap[son]: # 先把son指向最大的儿子
son += 1
if self.larger_heap[i] < self.larger_heap[son]: # 判断是否需要交换
self.larger_heap[i], self.larger_heap[son] = self.larger_heap[son], self.larger_heap[i]
i = son
else:
break
return ans
# 最小堆插入操作:
def smaller_heap_push(self, num):
self.smaller_heap.append(num)
n = len(self.smaller_heap)
i = n - 1
while i > 0:
if self.smaller_heap[i] < self.smaller_heap[(i-1)//2]:
self.smaller_heap[i], self.smaller_heap[(i-1)//2] = self.smaller_heap[(i-1)//2], self.smaller_heap[i]
i = (i-1)//2
else:
break
# 最小堆取出堆顶后调整堆:
def smaller_heap_pop(self):
ans = self.smaller_heap[0]
self.smaller_heap[0] = self.smaller_heap.pop()
n = len(self.smaller_heap)
i = 0
while 2 * i + 1 < n:
son = 2 * i + 1
if son + 1 < n and self.smaller_heap[son+1] < self.smaller_heap[son]:
son += 1
if self.smaller_heap[i] > self.smaller_heap[son]:
self.smaller_heap[i], self.smaller_heap[son] = self.smaller_heap[son], self.smaller_heap[i]
i = son
else:
break
return ans
def Insert(self, num):
# write code here
if (len(self.larger_heap) + len(self.smaller_heap)) % 2 == 1:
if self.smaller_heap and num > self.smaller_heap[0]:
self.smaller_heap_push(num)
num = self.smaller_heap_pop()
self.larger_heap_push(num)
else:
if self.larger_heap and num < self.larger_heap[0]:
self.larger_heap_push(num)
num = self.larger_heap_pop()
self.smaller_heap_push(num)
def GetMedian(self, n=None):
# write code here
n = len(self.larger_heap) + len(self.smaller_heap)
if n % 2 == 1:
return self.smaller_heap[0]
else:
return (self.smaller_heap[0] + self.larger_heap[0]) / 2.0