LeetCode480. 滑动窗口中位数(二分查找)

1、题目描述

https://leetcode-cn.com/problems/sliding-window-median/

中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数

  • [2,3,4],中位数是 3
  • [2,3],中位数是 (2 + 3) / 2 = 2.5

给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。

你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。

你可以假设 k 始终有效,即:k 始终小于输入的非空数组的元素个数。

  • 给出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。
  • 返回该滑动窗口的中位数数组 [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

2、代码详解

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(ax)

在 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)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值