wuxin0011`blog wuxin0011`blog
首页
  • 基础内容

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • JavaScript教程
    • ES6 教程
    • Vue
    • React
    • Typescript
    • Git
  • 推荐阅读
  • java随笔
  • JVM (opens new window)
  • 分类
  • 标签
  • 归档
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • git使用
  • docker部署项目
  • 错误收集
  • github-start
  • background-color
  • live-server
  • tampermonkey-script (opens new window)
  • leetcode-tool (opens new window)
  • 网站
  • 前端
  • 后端
  • Github Topic (opens new window)
GitHub (opens new window)

wuxin0011

懂得越多,懂得越少
首页
  • 基础内容

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • JavaScript教程
    • ES6 教程
    • Vue
    • React
    • Typescript
    • Git
  • 推荐阅读
  • java随笔
  • JVM (opens new window)
  • 分类
  • 标签
  • 归档
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • git使用
  • docker部署项目
  • 错误收集
  • github-start
  • background-color
  • live-server
  • tampermonkey-script (opens new window)
  • leetcode-tool (opens new window)
  • 网站
  • 前端
  • 后端
  • Github Topic (opens new window)
GitHub (opens new window)
  • LeetCode
  • ans
wuxin0011
2023-12-30
目录

二分法解决滑动窗口中位数

# 题目链接

滑动窗口中位数 (opens new window)

# 思路

如果不卡常数时间,暴力就能过,那就是简单题了

class Solution:
    def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
        n = len(nums)
        ans = [ ]
        def d(i):
            ls = nums[i:i+k]
            ls.sort()
            mid = k // 2
            f = 0
            if k % 2 == 0:
                f = (ls[mid-1] + ls[mid])/2
            else:
                f = ls[mid]
            return f

        for i in range(0,n-k+1):
            f = d(i)
            ans.append(f)
        return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

之所以特别耗时是因为不断排序 总时间复杂度为 O((n-k)(k)log(k)) 平均一下就是O(n*klog(k))

 ls = nums[i:i+k]
 ls.sort()
1
2

ls.sort() 排序时间复杂度为 O(klogk) ,可以看图演示

class Solution:
    def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
        n = len(nums)
        ans = []
        
        # 二分查找删除
        def remove(i,ls):
            # 最大
            pre = nums[i-1]
            if ls[-1] == pre:
                del ls[-1]
                return
            # 最小
            if ls[0] == pre:
                del ls[0]
                return

            l = 0
            r = k-1
            while l<=r:
                mid = l + (( r - l )>>1)
                if ls[mid] == pre:
                    # print("find",pre)
                    del ls[mid]
                    break
                elif ls[mid] > pre:
                    r = mid - 1
                else:
                    l = mid + 1

        # 二分查找插入
        def insert(i,ls):
            val = nums[i+k-1]
            l = 0
            r = k-1
            # 最大
            if  len(ls) == 0 or ls[-1] <= val:
                ls.append(val)
                return
            # 最小
            if ls[0] >= val:
                ls.insert(0, val)
                return
            # 1 2 8 3
            while l<=r:
                mid = l + (( r - l )>>1)
                if ls[mid] == val:
                    ls.insert(mid, val)
                    return
                elif ls[mid] > val:
                    r = mid-1
                else:
                    l = mid + 1
            ls.insert(l,val)
            
        def window(i,ls):
            if i >0:
                remove(i,ls)
                insert(i,ls)
            mid = k // 2
            f = 0
            if (k & 1) == 0:
                f = (ls[mid-1] + ls[mid])/2
            else:
                f = ls[mid]
            return f


        ls = nums[0:k]
        ls.sort() # 第一个保持有序
        f = window(0,ls)
        ans.append(f)
        # print('len = ',n,'max = ',n-k+1)
        for i in range(1,n-k+1):
            # print('cur = ',i+k-1,'pre = ',i-1)
            pre = nums[i-1]
            cur = nums[i+k-1]
            # print('pre ',pre,'cur ',cur,'before = ',f,'ls = ',ls,i,'max = ',n-k,',len =', n,',k = ',k,',index = ',i)
            # 当需要被移除的数不等于移入的数时才会改变
            if cur != pre:
                # print('UPDATE')
                # print(f,ls)
                f = window(i,ls)
                # print(f,ls)
            ans.append(f) # 保留上一次计算结果 如果相等直接跳过
        return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

解决一道hard题真不容易啊😭,目前只能想到这种方法了,更好的方法和优化方案等待中……

编辑 (opens new window)
#二分#滑动窗口
上次更新: 2024-05-21, 09:50:09
最近更新
01
LeetCode刷题工具之本地对拍
04-04
02
sublime对应语言模板使用技巧
02-28
03
经典字符串匹配算法
02-05
更多文章>
Theme by Vdoing | Copyright © 2020-2024 wuxin0011 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式