https://leetcode-cn.com/problems/sliding-window-median/
中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。
你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。
你可以假设 k
始终有效,即:k
始终小于输入的非空数组的元素个数。
[1,-1,-1,3,5,6]
。窗口位置 中位数
--------------- -----
[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
https://leetcode-cn.com/problems/sliding-window-median/solution/python3-chao-xiang-xi-duo-jie-fa-bao-li-ga02a/
对每个滑动窗口中先排序,再求中位数
class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
median = lambda a: (a[(len(a) - 1) // 2] + a[len(a) // 2]) / 2 # 注意python2的/只保留整数
res = []
for i in range(len(nums) - k + 1):
res.append(median(sorted(nums[i:i + k])))
return res
①lambda函数用法 https://www.cnblogs.com/kaishirenshi/p/8611358.html
lambda匿名函数的格式:冒号前是参数,可以有多个,用逗号隔开,冒号右边的为表达式。其实lambda返回值是一个函数的地址,也就是函数对象。
时间复杂度:O(n k log k),排序的时间复杂度为O(k log k),总共执行了 n 次。
import bisect
from typing import List
class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
median = lambda a: (a[(len(a)-1)//2] + a[len(a)//2]) / 2
a = sorted(nums[:k])
res = [median(a)]
for i, j in zip(nums[:-k], nums[k:]):
# print('i:', i, 'j:', j)
a.remove(i)
a.insert(bisect.bisect_left(a, j), j)
# print('a:', a)
res.append(median(a))
return res
nums = [1,3,-1,-3,5,3,6,7]
k = 3
s = Solution()
print(s.medianSlidingWindow(nums, k))
'''i,j'''
i: 1 j: -3
i: 3 j: 5
i: -1 j: 3
i: -3 j: 6
i: 5 j: 7
'''a:'''
i: 1 j: -3
a: [-3, -1, 3]
i: 3 j: 5
a: [-3, -1, 5]
i: -1 j: 3
a: [-3, 3, 5]
i: -3 j: 6
a: [3, 5, 6]
i: 5 j: 7
a: [3, 6, 7]
'''res'''
[1.0, -1.0, -1.0, 3.0, 5.0, 6.0]
①bisect — 数组二分查找算法 https://docs.python.org/zh-cn/2/library/bisect.html
bisect_left
(a, x)
在 a 中找到 x 合适的插入点index以维持有序。
②zip:将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
https://www.runoob.com/python/python-func-zip.html
>>>a = [1,2,3]
>>> b = [4,5,6]
>>> zipped = zip(a,b) # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
时间复杂度:O(nk)