原题地址(困难)

方法1—优先队列/堆

思路

这题真的太难了

这题是在295题基础之上,难度我感觉又提升了一个level
295. 数据流的中位数
295题是单纯的双优先队列,而这题,又加了 延迟删除 的思想,这是最难的地方。
直接看了官方题解,照着它的思路写了代码。

代码

  1. class DualHeap:
  2. def __init__(self, k: int):
  3. self.maxHeap = []
  4. self.minHeap = []
  5. self.delayed = collections.Counter()
  6. self.k = k
  7. self.maxHeapSize = 0
  8. self.minHeapSize = 0
  9. def prune(self, heap): # 不断删除堆顶元素,更新哈希表,为的是保证堆顶元素是不需要被延迟删除的
  10. while heap:
  11. num = heap[0] # 堆顶元素
  12. if heap is self.maxHeap: # 大顶堆要取反
  13. num = -num
  14. if num in self.delayed: # 这个堆顶元素需要删除
  15. self.delayed[num] -= 1
  16. if self.delayed[num] == 0:
  17. self.delayed.pop(num)
  18. heapq.heappop(heap)
  19. else:
  20. break
  21. def makeBalance(self): # 调整大根堆小根堆的元素个数
  22. if self.maxHeapSize - self.minHeapSize >= 2:
  23. maxHeapTop = -heapq.heappop(self.maxHeap) # 得到堆顶元素
  24. heapq.heappush(self.minHeap, maxHeapTop) # 放入小顶堆
  25. self.maxHeapSize -= 1
  26. self.minHeapSize += 1
  27. self.prune(self.maxHeap)
  28. elif self.minHeapSize > self.maxHeapSize:
  29. minHeapTop = heapq.heappop(self.minHeap)
  30. heapq.heappush(self.maxHeap, -minHeapTop)
  31. self.minHeapSize -= 1
  32. self.maxHeapSize += 1
  33. self.prune(self.minHeap)
  34. def insert(self, num): # 插入
  35. if not self.maxHeap or num <= -self.maxHeap[0]:
  36. heapq.heappush(self.maxHeap, -num)
  37. self.maxHeapSize += 1
  38. else:
  39. heapq.heappush(self.minHeap, num)
  40. self.minHeapSize += 1
  41. self.makeBalance()
  42. def erase(self, num): # 删除
  43. self.delayed[num] += 1
  44. if num <= -self.maxHeap[0]:
  45. self.maxHeapSize -= 1
  46. if num == -self.maxHeap[0]:
  47. self.prune(self.maxHeap)
  48. else:
  49. self.minHeapSize -= 1
  50. if num == self.minHeap[0]:
  51. self.prune(self.minHeap)
  52. self.makeBalance()
  53. def getMedian(self): # 得到中位数
  54. return -self.maxHeap[0] if self.k & 1 else (-self.maxHeap[0] + self.minHeap[0]) / 2
  55. class Solution:
  56. def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
  57. dh = DualHeap(k)
  58. for num in nums[:k]: # 初始化
  59. dh.insert(num)
  60. ans = [dh.getMedian()]
  61. for i in range(k, len(nums)):
  62. dh.insert(nums[i])
  63. dh.erase(nums[i-k])
  64. ans.append(dh.getMedian())
  65. return ans

时空复杂度

时间复杂度O(logN)
空间复杂度O(N)