【題目】
有乙個源源不斷地吐出整數的資料流,假設你有足夠的空間來儲存吐出的數。請設計乙個名叫medianholder的結構,medianholder可以隨時取得之前吐出所有數的中位數。
【要求】
如果medianholder已經儲存了吐出的n個數,那麼任意時刻將乙個新數加入到medianholder的過程,其時間複雜度o(logn)。
取得已經吐出的n個數整體的中位數的過程,時間複雜度o(1)。
【基本思路】
使用兩個堆結構,乙個大根堆,乙個小根堆。將接收的所有數的較小的一半放入大根堆,將接收的較大的一半放入小根堆。如果接收的個數為奇數,中位數就是小根堆和大根堆中元素數量多的那個堆的堆頂,比如吐出的數是6,1,3,0,9,8,7,小根堆中存放6,7,8,9,大根堆存放0,1,3,小根堆的元素個數多,它的堆頂就是該序列的中位數,即6;如果接收的個數是偶數,中位數就是兩個堆頂相加除以2。
每次接收到乙個數,都要正確選擇放入哪個堆,小於小根堆堆頂的都放入大根堆,否則放入小根堆。如果出現乙個堆的元素個數比另乙個堆的元素多兩個的情況,將前者的堆頂彈出新增到後者中,並重新調整兩個堆。總之要始終保持兩個堆元素個數的差值不大於1。
這樣隨時都可以知道已經吐出的所有數處於中間位置的兩個數是什麼,取得中位數的操作時間複雜度為o(1),同時根據堆的性質,向堆中新增乙個新數,並且調整堆的代價為o(logn)。然而題目有乙個很重要的限制「任意時刻將乙個新數加入到medianholder的過程,其時間複雜度o(logn)」,為了做到「任何時刻」的要求,那麼堆的設計不能採用固定陣列的實現方式,因為會有擴容的負擔。為了解決這個問題,需要設計乙個沒有擴容負擔的堆結構,具體實現參照另一篇部落格設計乙個沒有擴容負擔的堆結構。
【**實現】
#python3.5
defminheapcomparator
(a, b):
if a <= b:
return
false
if a > b:
return
true
defmaxheapcomparator
(a, b):
if a >= b:
return
false
else:
return
true
class
medianholder:
def__init__
(self):
self.minheap = myheap(minheapcomparator)
self.maxheap = myheap(maxheapcomparator)
defaddnum
(self, num):
if self.maxheap.isempty():
self.maxheap.add(num)
return
if self.maxheap.gethead() >= num:
self.maxheap.add(num)
else:
if self.minheap.isempty():
self.minheap.add(num)
elif self.minheap.gethead() > num:
self.maxheap.add(num)
else:
self.minheap.add(num)
self.modifytwoheapsize()
defmodifytwoheapsize
(self):
if self.minheap.getsize() == self.maxheap.getsize() + 2:
self.maxheap.add(self.minheap.pophead())
if self.maxheap.getsize() == self.minheap.getsize() + 2:
self.minheap.add(self.maxheap.pophead())
defgetmedian
(self):
maxheapsize = self.maxheap.getsize()
minheapsize = self.minheap.getsize()
if maxheapsize + minheapsize == 0:
return
none
if (maxheapsize + minheapsize) & 1 == 0:
return (self.maxheap.gethead() + self.minheap.gethead()) / 2
else:
if maxheapsize > minheapsize:
return self.maxheap.gethead()
else:
return self.minheap.gethead()
隨時找到資料流的中位數
題目 有乙個源源不斷地吐出整數的資料流,假設你有足夠的空間來儲存吐出的數。請設計乙個名叫medianholder的結構,medianholder可以隨時取得之前吐出所有數的中位數。要求 1 如果medianholder已經儲存了吐出的n個數,那麼任意時刻將乙個新數加入到medianholder的過程...
隨時找到資料流的中位數
題目描述 有乙個源源不斷地吐出整數的資料流,假設你有足夠的空間來儲存吐出的數。請設計乙個名叫medianholder的結構,medianholder可以隨時取得之前吐出所有數的中位數。要求 方法方法1 我們收集到資料之後排序,這樣的時間複雜度就是排序的時間複雜度最好也是o nlogn 無法滿足要求 ...
隨時找到資料流的中位數
有乙個源源不斷的吐出整數的資料流,假設你有足夠的空間來儲存吐出的數。請設計乙個名叫medianholder的結構,medianholder可以隨時取得之前吐出所有數的中位數。要求 1.如果medianholder已經儲存了吐出的n個數,那麼將乙個新數加入到medianholder的過程,其時間複雜度...