原题地址(困难)
方法1—优先队列/堆
思路
这题真的太难了
这题是在295题基础之上,难度我感觉又提升了一个level
295. 数据流的中位数
295题是单纯的双优先队列,而这题,又加了 延迟删除 的思想,这是最难的地方。
直接看了官方题解,照着它的思路写了代码。
代码
class DualHeap:def __init__(self, k: int):self.maxHeap = []self.minHeap = []self.delayed = collections.Counter()self.k = kself.maxHeapSize = 0self.minHeapSize = 0def prune(self, heap): # 不断删除堆顶元素,更新哈希表,为的是保证堆顶元素是不需要被延迟删除的while heap:num = heap[0] # 堆顶元素if heap is self.maxHeap: # 大顶堆要取反num = -numif num in self.delayed: # 这个堆顶元素需要删除self.delayed[num] -= 1if self.delayed[num] == 0:self.delayed.pop(num)heapq.heappop(heap)else:breakdef makeBalance(self): # 调整大根堆小根堆的元素个数if self.maxHeapSize - self.minHeapSize >= 2:maxHeapTop = -heapq.heappop(self.maxHeap) # 得到堆顶元素heapq.heappush(self.minHeap, maxHeapTop) # 放入小顶堆self.maxHeapSize -= 1self.minHeapSize += 1self.prune(self.maxHeap)elif self.minHeapSize > self.maxHeapSize:minHeapTop = heapq.heappop(self.minHeap)heapq.heappush(self.maxHeap, -minHeapTop)self.minHeapSize -= 1self.maxHeapSize += 1self.prune(self.minHeap)def insert(self, num): # 插入if not self.maxHeap or num <= -self.maxHeap[0]:heapq.heappush(self.maxHeap, -num)self.maxHeapSize += 1else:heapq.heappush(self.minHeap, num)self.minHeapSize += 1self.makeBalance()def erase(self, num): # 删除self.delayed[num] += 1if num <= -self.maxHeap[0]:self.maxHeapSize -= 1if num == -self.maxHeap[0]:self.prune(self.maxHeap)else:self.minHeapSize -= 1if num == self.minHeap[0]:self.prune(self.minHeap)self.makeBalance()def getMedian(self): # 得到中位数return -self.maxHeap[0] if self.k & 1 else (-self.maxHeap[0] + self.minHeap[0]) / 2class Solution:def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:dh = DualHeap(k)for num in nums[:k]: # 初始化dh.insert(num)ans = [dh.getMedian()]for i in range(k, len(nums)):dh.insert(nums[i])dh.erase(nums[i-k])ans.append(dh.getMedian())return ans
时空复杂度
时间复杂度O(logN)
空间复杂度O(N)
