📅  最后修改于: 2023-12-03 14:54:59.608000             🧑  作者: Mango
在计算机科学中,数组中滑动窗口的中位数问题是指给定一个长度为n的数组nums,以及一个大小为k的滑动窗口在nums上从左到右滑动,找出每个滑动窗口内的中位数。该问题有两个版本,第一个版本是要求找出每个滑动窗口中的中位数。第二个版本是要求找出滑动窗口中所有数字的中位数。
在窗口逐步移动时,可以先将窗口内的元素排序,然后找出其中位数即可。为了避免重复排序导致时间复杂度过高,可以使用一个有序数据结构,如堆或红黑树,来维护窗口内的元素。在窗口移动时,将左侧的元素从数据结构中删除,将右侧的元素添加到数据结构中,然后找出其中位数即可。时间复杂度为O(nlogk)。
from heapq import *
class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
if not nums or k == 0:
return []
max_heap = []
min_heap = []
res = []
for i in range(len(nums)):
if max_heap and nums[i] <= -max_heap[0]:
heappush(max_heap, -nums[i])
else:
heappush(min_heap, nums[i])
if i >= k:
if nums[i - k] <= -max_heap[0]:
max_heap.remove(-nums[i - k])
heapify(max_heap)
else:
min_heap.remove(nums[i - k])
heapify(min_heap)
if len(max_heap) > len(min_heap) + 1:
heappush(min_heap, -heappop(max_heap))
elif len(min_heap) > len(max_heap):
heappush(max_heap, -heappop(min_heap))
if i >= k - 1:
if k % 2 == 0:
res.append((-max_heap[0] + min_heap[0]) / 2)
else:
res.append(-max_heap[0])
return res
首先建立一个大小为k的最小堆和一个大小为k的最大堆,用于维护当前窗口内的元素。然后将堆分为两个区间,一个小于等于中位数的区间,一个大于中位数的区间。当k为偶数时,中位数为中间两个数的平均数,即(max_heap[0] + min_heap[0]) / 2。当k为奇数时,中位数为最大堆堆顶元素,即-max_heap[0]。时间复杂度为O(nlogk)。
from heapq import *
class MedianFinder:
def __init__(self):
self.max_heap = []
self.min_heap = []
def addNum(self, num: int) -> None:
heappush(self.max_heap, -num)
heappush(self.min_heap, -heappop(self.max_heap))
if len(self.min_heap) > len(self.max_heap):
heappush(self.max_heap, -heappop(self.min_heap))
def findMedian(self) -> float:
if len(self.max_heap) > len(self.min_heap):
return -self.max_heap[0]
else:
return (self.min_heap[0] - self.max_heap[0]) / 2
class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
if not nums or k == 0:
return []
mf = MedianFinder()
for i in range(k):
mf.addNum(nums[i])
res = [mf.findMedian()]
for i in range(k, len(nums)):
mf.addNum(nums[i - k])
res.append(mf.findMedian())
return res
以上就是数组中滑动窗口的中位数问题的两个版本的解决方案,具体实现可根据实际情况调整。