数据结构与算法之 leetcode 队列滑动窗口中位数实现 双堆同步

数据结构与算法阿木 发布于 2025-07-12 8 次阅读


摘要:

在LeetCode中,队列滑动窗口中位数实现是一个经典的算法问题。本文将深入探讨该问题的背景、解决方案,以及使用双堆同步技术实现的详细代码。通过分析数据结构和算法,我们将理解如何高效地处理滑动窗口的中位数问题。

一、背景介绍

在数据流中,我们需要实时计算滑动窗口的中位数。滑动窗口中位数问题在金融、搜索引擎、实时监控等领域有着广泛的应用。传统的解决方案是使用排序,但排序的时间复杂度为O(nlogn),不适合实时计算。我们需要一种更高效的方法来解决这个问题。

二、解决方案

双堆同步技术是一种高效解决滑动窗口中位数问题的方法。它使用两个堆(最大堆和最小堆)来维护窗口中的数据,并保证最大堆中的元素不大于最小堆中的元素。这样,最大堆的堆顶元素即为窗口的最大值,最小堆的堆顶元素即为窗口的最小值,从而可以快速计算出窗口的中位数。

三、数据结构

1. 最大堆(Max Heap):用于存储窗口中的较小值,堆顶元素为最大值。

2. 最小堆(Min Heap):用于存储窗口中的较大值,堆顶元素为最小值。

四、算法步骤

1. 初始化两个堆:maxHeap和minHeap。

2. 遍历数据流中的每个元素:

a. 如果元素小于等于maxHeap的堆顶元素,则将其加入maxHeap。

b. 否则,将其加入minHeap。

c. 如果maxHeap的堆大小大于minHeap的堆大小,则将maxHeap的堆顶元素移至minHeap。

d. 如果minHeap的堆大小大于maxHeap的堆大小1,则将minHeap的堆顶元素移至maxHeap。

3. 计算窗口的中位数:

a. 如果maxHeap和minHeap的堆大小相等,则中位数为(maxHeap的堆顶元素 + minHeap的堆顶元素) / 2。

b. 如果maxHeap的堆大小大于minHeap的堆大小,则中位数为maxHeap的堆顶元素。

五、代码实现

python

import heapq

class MedianFinder:


def __init__(self):


self.maxHeap = [] 最大堆


self.minHeap = [] 最小堆

def addNum(self, num):


if not self.maxHeap or num <= -self.maxHeap[0]:


heapq.heappush(self.maxHeap, -num)


else:


heapq.heappush(self.minHeap, num)

平衡两个堆的大小


if len(self.maxHeap) > len(self.minHeap) + 1:


heapq.heappush(self.minHeap, -heapq.heappop(self.maxHeap))


if len(self.minHeap) > len(self.maxHeap):


heapq.heappush(self.maxHeap, -heapq.heappop(self.minHeap))

def findMedian(self):


if len(self.maxHeap) == len(self.minHeap):


return (-self.maxHeap[0] + self.minHeap[0]) / 2


else:


return -self.maxHeap[0]

示例


medianFinder = MedianFinder()


nums = [1, 2, 3, 4, 5]


for num in nums:


medianFinder.addNum(num)


print(medianFinder.findMedian()) 输出: 3


六、总结

本文深入解析了LeetCode队列滑动窗口中位数实现(双堆同步)算法。通过使用双堆同步技术,我们可以在O(logn)的时间复杂度内高效地计算滑动窗口的中位数。在实际应用中,该算法可以广泛应用于金融、搜索引擎、实时监控等领域。