如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.littlevalueMaxHeap = []
self.bigvalueMinHeap = []
self.maxHeapCount = 0
self.minHeapCount = 0
def Insert(self, num):
if self.minHeapCount < self.maxHeapCount:
self.minHeapCount +=1
if num < self.littlevalueMaxHeap[0]:
tmpNum = self.littlevalueMaxHeap[0]
self.adjustMaxHeap(num)
self.createMinHeap(tmpNum)
else:
self.createMinHeap(num)
else:
self.maxHeapCount+=1
if len(self.littlevalueMaxHeap)==0:
self.createMaxHeap(num)
else:
if self.bigvalueMinHeap[0]<num:
tmpNum=self.bigvalueMinHeap[0]
self.adjustMinHeap(num)
self.createMaxHeap(tmpNum)
else:
self.createMaxHeap(num)
def GetMedian(self):
if self.minHeapCount<self.maxHeapCount:
return self.littlevalueMaxHeap[0]
else:
return (self.littlevalueMaxHeap[0]+self.bigvalueMinHeap[0])/2
def createMaxHeap(self, num):
self.littlevalueMaxHeap.append(num)
tmpIndex = len(self.littlevalueMaxHeap) - 1
while tmpIndex:
parentIndex = (tmpIndex - 1) // 2
if self.littlevalueMaxHeap[parentIndex] < self.littlevalueMaxHeap[tmpIndex]:
self.littlevalueMaxHeap[parentIndex], self.littlevalueMaxHeap[tmpIndex] =\
self.littlevalueMaxHeap[tmpIndex], self.littlevalueMaxHeap[parentIndex]
tmpIndex=parentIndex
else:
break
def adjustMaxHeap(self,num):
if num<self.littlevalueMaxHeap[0]:
self.littlevalueMaxHeap[0]=num
maxHeapLen = len(self.littlevalueMaxHeap)
tmpIndex=0
while tmpIndex< maxHeapLen:
leftIndex = tmpIndex*2+1
rightIndex = tmpIndex*2+2
largerIndex = 0
if rightIndex < maxHeapLen:
largerIndex = rightIndex if self.littlevalueMaxHeap[leftIndex]<self.littlevalueMaxHeap[rightIndex] else leftIndex
elif leftIndex < maxHeapLen:
largerIndex = leftIndex
else:
break
if self.littlevalueMaxHeap[tmpIndex] <self.littlevalueMaxHeap[largerIndex]:
self.littlevalueMaxHeap[tmpIndex], self.littlevalueMaxHeap[largerIndex] = self.littlevalueMaxHeap[largerIndex], self.littlevalueMaxHeap[tmpIndex]
tmpIndex = largerIndex
else:
break
def createMinHeap(self, num):
self.bigvalueMinHeap.append(num)
tmpIndex = len(self.bigvalueMinHeap) - 1
while tmpIndex:
parentIndex = (tmpIndex - 1) // 2
if self.bigvalueMinHeap[tmpIndex]<self.bigvalueMinHeap[parentIndex] :
self.bigvalueMinHeap[parentIndex], self.bigvalueMinHeap[tmpIndex] = \
self.bigvalueMinHeap[tmpIndex], self.bigvalueMinHeap[parentIndex]
tmpIndex=parentIndex
else:
break
def adjustMinHeap(self,num):
if num<self.bigvalueMinHeap[0]:
self.bigvalueMinHeap[0]=num
minHeapLen = len(self.bigvalueMinHeap)
tmpIndex=0
while tmpIndex< minHeapLen:
leftIndex = tmpIndex*2+1
rightIndex = tmpIndex*2+2
smallerIndex = 0
if rightIndex < minHeapLen:
smallerIndex = rightIndex if self.bigvalueMinHeap[rightIndex]<self.bigvalueMinHeap[leftIndex] else leftIndex
elif leftIndex < minHeapLen:
smallerIndex = leftIndex
else:
break
if self.bigvalueMinHeap[smallerIndex] < self.bigvalueMinHeap[tmpIndex]:
self.bigvalueMinHeap[tmpIndex], self.bigvalueMinHeap[smallerIndex] = self.bigvalueMinHeap[smallerIndex], self.littlevalueMaxHeap[tmpIndex]
tmpIndex = smallerIndex
else:
break
if __name__ == '__main__':
s=Solution()
for i in [5,2,3,4,1,6,7,0,8]:
s.Insert(i)
print(s.GetMedian())
运行结果为:
5
3.5
3
3.5
3
3.5
4
3.5
4
将以上代码封装,简洁后的代码:
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.littlevalueMaxHeap = []
self.bigvalueMinHeap = []
self.maxHeapCount = 0
self.minHeapCount = 0
def Insert(self, num):
def cmpMaxHeap(a, b):
return a > b
def cmpMinHeap(a, b):
return a < b
if self.minHeapCount < self.maxHeapCount:
self.minHeapCount += 1
if num < self.littlevalueMaxHeap[0]:
tmpNum = self.littlevalueMaxHeap[0]
self.adjustHeap(num, self.littlevalueMaxHeap, cmpMaxHeap)
self.createHeap(tmpNum, self.bigvalueMinHeap, cmpMinHeap)
else:
self.createHeap(num, self.bigvalueMinHeap, cmpMinHeap)
else:
self.maxHeapCount += 1
if len(self.littlevalueMaxHeap) == 0:
self.createHeap(num, self.littlevalueMaxHeap, cmpMaxHeap)
else:
if self.bigvalueMinHeap[0] < num:
tmpNum = self.bigvalueMinHeap[0]
self.adjustHeap(num, self.bigvalueMinHeap, cmpMinHeap)
self.createHeap(tmpNum, self.littlevalueMaxHeap, cmpMaxHeap)
else:
self.createHeap(num, self.littlevalueMaxHeap, cmpMaxHeap)
def GetMedian(self):
if self.minHeapCount < self.maxHeapCount:
return self.littlevalueMaxHeap[0]
else:
return (self.littlevalueMaxHeap[0] + self.bigvalueMinHeap[0]) / 2
def createHeap(self, num, heap, cmpfun):
heap.append(num)
tmpIndex = len(heap) - 1
while tmpIndex:
parentIndex = (tmpIndex - 1) // 2
if cmpfun(heap[tmpIndex], heap[parentIndex]):
heap[parentIndex], heap[tmpIndex] = heap[tmpIndex], heap[parentIndex]
tmpIndex = parentIndex
else:
break
def adjustHeap(self, num, heap, cmpFunc):
if num < heap[0]:
heap[0] = num
maxHeapLen = len(heap)
tmpIndex = 0
while tmpIndex < maxHeapLen:
leftIndex = tmpIndex * 2 + 1
rightIndex = tmpIndex * 2 + 2
largerIndex = 0
if rightIndex < maxHeapLen:
largerIndex = rightIndex if cmpFunc(heap[rightIndex], heap[leftIndex]) else leftIndex
elif leftIndex < maxHeapLen:
largerIndex = leftIndex
else:
break
if cmpFunc(heap[largerIndex], heap[tmpIndex]):
heap[tmpIndex], heap[largerIndex] = heap[largerIndex], heap[tmpIndex]
tmpIndex = largerIndex
else:
break
if __name__ == '__main__':
s = Solution()
for i in [5, 2, 3, 4, 1, 6, 7, 0, 8]:
s.Insert(i)
print(s.GetMedian())
运行结果为:
5
3.5
3
3.5
3
3.5
4
3.5
4