• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LilyLiya
博客园    首页    新随笔    联系   管理    订阅  订阅
Continuous Median
Heap constructions, min heap, max heap, rebalance heaps ,find medians

refer to: https://www.algoexpert.io/questions/Continuous%20Median


Problem statement

Analysis

O(N) for insert one number into a sorted array

Code

def MAX_HEAP_FUNC(a, b):
        return a > b
    
def MIN_HEAP_FUNC(a, b):
        return a < b

class ContinuousMedianHandler:
    def __init__(self):
        self.lowers = Heap(MAX_HEAP_FUNC, []) #create a maxheap for lower half of the numbers
        self.greaters = Heap(MIN_HEAP_FUNC, []) #create a minheap for greater half of the numbers
        self.median = None

    def insert(self, number): 
        if not self.lowers.length or number < self.lowers.peek():#empty lower heap or the new number < the peek of the lower maxheap
            self.lowers.insert(number)
        else:
            self.greaters.insert(number)
        self.rebalanceHeaps() # balance the lower and greater heaps, make sure the different between their lengths <= 1
        self.updateMedian() #update new median value
        
    def rebalanceHeaps(self):
        if self.lowers.length - self.greaters.length == 2: # lower heap has more values
            self.greater.insert(self.lowers.remove())# remove the peek(max value) of the lower heap into the greater heap
        elif self.greaters.length - self.lowers.length == 2:
            self.lowers.insert(self.greaters.remove())
    def updateMedian(self): 
        if self.lowers.length == self.greaters.length: # same length, the two mid values are peeks of low and great heaps
            self.median = (self.lowers.peek() + self.greaters.peek())/2
        elif self.lowers.length > self.greaters.length: # lower heap has more one valye, the peek one of lower heap
            self.median = self.lowers.peek()
        else: # higher heap has more one value
            self.median = self.greaters.peek()
    def getMedian(self):
        return self.median

Time and space complexity

time: log(n) time for insert, remove in heaps.

space: store all the numbers in heap->O(N)

The Heap class

 

class Heap:
    def __init__(self, comparisonFunc, array):
        self.comparisonFunc = comparisonFunc
        self.heap = self.buildHeap(array)
        self.length = len(self.heap)
    def buildHeap(self, array):
        firstParentIdx = (len(array) - 2) //2
        for currentIdx in reversed(range(firstParentIdx + 1)):
            self.siftDown(currentIdx, len(array) - 1, array)
        return array
    def siftDown(self, currentIdx, endIdx, heap):
        childOneIdx = currentIdx *2 + 1
        while childOneIdx <= endIdx:
            childTwoIdx = currentIdx * 2 + 2 if currentIdx * 2 + 2 <= endIdx else - 1
            if childTwoIdx != -1:
                if self.comparisonFunc(heap[childTwoIdx], heap[childOneIdx]):
                    idxToSwap = childTwoIdx
                else:
                    idxToSwap = childOneIdx
            else:
                idxToSwap = childOneIdx
            if self.comparisonFunc(heap[idxToSwap], heap[currentIdx]):
                self.swap(currentIdx, idxToSwap, heap)
                currentIdx = idxToSwap
                childOneIdx = currentIdx * 2 + 1
            else:
                return
    
    def siftUp(self, currentIdx, heap):
        parentIdx = (currentIdx - 1) // 2
        while currentIdx > 0:
            if self.comparisonFunc(heap[currentIdx], heap[parentIdx]):
                self.swap(currentIdx, parentIdx, heap)
                currentIdx = parentIdx
                parentIdx = (currentIdx - 1) // 2
            else:
                return
    
    def peek(self):
        return self.heap[0]

    
    def remove(self):
        self.swap(0, self.length - 1, self.heap)
        valueToRemove = self.heap.pop()
        self.length -= 1
        self.siftDown(0, self.length - 1, self.heap)
        return valueToRemove
    
    def insert(self, value):
        self.heap.append(value)
        self.length += 1
        self.siftUp(self.length - 1, self.heap)
        
    def swap(self, i, j, array):
        array[i],array[j] = array[j], array[i]
        

 

posted on 2021-06-10 06:49  LilyLiya  阅读(51)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3