原题
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples:
[2,3,4] , the median is 3
[2,3], the median is (2 + 3) / 2 = 2.5
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Your job is to output the median array for each window in the original array.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
Window position Median
[1 3 -1] -3 5 3 6 7 1
1 [3 -1 -3] 5 3 6 7 -1
1 3 [-1 -3 5] 3 6 7 -1
1 3 -1 [-3 5 3] 6 7 3
1 3 -1 -3 [5 3 6] 7 5
1 3 -1 -3 5 [3 6 7] 6
Therefore, return the median sliding window as [1,-1,-1,3,5,6].
Note:
You may assume k is always valid, ie: k is always smaller than input array’s size for non-empty array.
解法
定义长度为K的滑动窗口, 遍历列表, 每次遍历时将中值加到结果中, 由于滑动窗口里的数字是升序排列, 我们使用二分搜索法查找nums[i-k]的元素在滑动窗口的位置(比用remove快), 删除该元素, 然后插入nums[i]到滑动窗口, 使用bisect.insert_left使得插入元素后滑动窗口保存升序排列.
Time: O(n)
Space: O(1)
代码
class Solution:
def medianSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[float]
"""
# base case
if k == 0: return []
win = sorted(nums[:k])
ans = []
for i in range(k, len(nums)+1):
median = (win[k//2] + win[(k-1)//2])/2.0
ans.append(median)
if i == len(nums):
break
# get the index of the nums[i-k] and then delete it, then insort nums[i]
index = bisect.bisect_left(win, nums[i-k])
win.pop(index)
bisect.insort_left(win, nums[i])
return ans