返回
为用户展现专业解答,助力提升用户体验——基于LeetCode 295 数据流的中位数的深入剖析
前端
2024-02-03 17:42:07
深入剖析LeetCode 295:数据流的中位数
问题陈述
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / 2 = 2.5 设计一个支持以下两种操作的数据结构:
addNum(val)
- 添加一个整数val
到数据结构中。findMedian()
- 返回目前所有元素的中位数。
示例:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2
算法概述
为了解决LeetCode 295 数据流的中位数问题,我们提出一种基于最小堆和最大堆的解决方案。基本思路是将输入数据流分成两半:左半部分(最大堆)存储较小的元素,右半部分(最小堆)存储较大的元素。这样,中位数就是两个堆顶元素的平均值(如果输入数据流的长度为偶数)或左堆顶元素(如果输入数据流的长度为奇数)。
实现细节
import heapq
class MedianFinder:
def __init__(self):
# 最小堆,存储较大的元素
self.max_heap = []
# 最大堆,存储较小的元素
self.min_heap = []
def addNum(self, val):
# 将新元素添加到最小堆
heapq.heappush(self.min_heap, -val)
# 将最小堆的根元素(最大值)移动到最大堆
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
# 平衡两个堆的大小,确保最大堆始终比最小堆多一个元素
if len(self.max_heap) > len(self.min_heap):
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
def findMedian(self):
# 如果两个堆的大小相同,中位数是两个堆顶元素的平均值
if len(self.max_heap) == len(self.min_heap):
return (self.max_heap[0] - self.min_heap[0]) / 2
# 否则,中位数是最大堆的根元素
else:
return -self.max_heap[0]
# 示例
median_finder = MedianFinder()
median_finder.addNum(1)
median_finder.addNum(2)
print(median_finder.findMedian()) # 输出:1.5
median_finder.addNum(3)
print(median_finder.findMedian()) # 输出:2
算法分析
时间复杂度:
addNum
操作的时间复杂度为O(log n),其中n是当前数据流的长度。findMedian
操作的时间复杂度为O(1),因为中位数可以直接从两个堆顶元素中计算得出。
空间复杂度:
算法的空间复杂度为O(n),因为需要使用两个堆来存储数据。
应用场景
LeetCode 295 数据流的中位数算法在许多场景中都有应用,例如:
- 在数据分析中,中位数可以用来衡量一组数据的中心趋势。
- 在机器学习中,中位数可以用来处理异常值。
- 在网络通信中,中位数可以用来计算数据包的平均延迟。
结语
LeetCode 295 数据流的中位数是一个经典的算法问题,其解决方案需要对数据结构和算法有深入的理解。本文详细介绍了基于最小堆和最大堆的解决方案,并分析了算法的时间复杂度和空间复杂度。希望这篇文章对您理解LeetCode 295 数据流的中位数问题有所帮助。