📜  数组中滑动窗口的中位数| 2套(1)

📅  最后修改于: 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

以上就是数组中滑动窗口的中位数问题的两个版本的解决方案,具体实现可根据实际情况调整。