题目

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释: 滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
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 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

提示:

你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

进阶:

你能在线性时间复杂度内解决此题吗?

解答

方法一:暴力破解。cur表示窗口,记录最大值,依次后移。时间复杂度O(n·k),太慢了,才超过30%的代码

方法二:用大顶堆存窗口元素,堆顶就是当前窗口最大值,依次后移,删除最左边,加入一个新元素,堆删除操作时间复杂度O(log(n)),插入操作O(1),这种方法总的时间复杂度O(n·log(k))。

But!Python中没有大顶堆的实现,用“存入堆、从堆中取出的时候,都用相反数”模拟大顶堆可行,以为这就解决了吗? No! heapq包可以删除堆顶元素,但没提供删除堆中某元素的方法,所有先找到元素在堆中位置再用了del删除,del删除后,存储堆的列表顺序就不是堆了,需要重新排列成堆,时间复杂度O(n),所以用Python最后做出来时间复杂度O(n·k),但这个提交速度为毛没有暴力破解快,无语。。。

方法三:双向队列,时间复杂度O(n)

思路:依次遍历列表中的元素,cur存放已经在窗口中的元素的下标,假如当前元素为c, 则用c和cur中元素从后向前比较,删除cur中小于c的元素,并把c的下标加到cur中,这步操作保证了cur[0]表示的元素永远是窗口中最大的

注:c和cur比较时,一定要从后往前,否则部分样例不能通过:[1, 3, 1, 2, 0, 5], k=3 .........................视频里讲的从前往后:)

通过代码如下:

from heapq import *

class Solution:

    # 方法一:暴力破解
# def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
# if not nums:
# return []
# ans = []
# cur = []
# for x in range(k):
# cur.append(nums[x]) # ans.append(max(cur))
# while x < len(nums)-1:
# del cur[0] # 删除表头
# cur.append(nums[x+1]) # 添加到尾
# ans.append(max(cur)) # max()的平均时间复杂度是O(n)
# x = x+1
# return ans # 方法二:大顶堆
# def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
# if not nums:
# return []
# l = [] # 预存堆
# ans = []
# for index, x in enumerate(nums):
# if index==0 or len(l)<k: # 堆还没满,入堆
# heappush(l, -x)
# else:
# ans.append(-l[0]) # 堆顶,最小的,取负数刚好是最大的
# del l[l.index(-nums[index-k])] # 删除窗口左侧第一个
# heappush(l, -x) # 入堆
# heapify(l) # 堆貌似乱了......, 重新排列成堆,时间复杂度是O(n)。。。
# ans.append(-l[0])
# return ans # 方法三:双端队列
def maxSlidingWindow(self, nums, k):
if not nums:
return []
cur = [] # 存窗口元素的index,cur[0]位置永远是最大的
ans = []
for index, x in enumerate(nums):
if index >= k and index - k >= cur[0]: # cur[0]和当前元素的index距离为k,说明cur[0]该从窗口删除了
cur.pop(0)
while cur and x >= nums[cur[-1]]: # 这里,cur要从后往前删小于当前元素的值
cur.pop()
cur.append(index) if index + 1 >= k: # 当前元素位已经走过了窗口距离大小
ans.append(nums[cur[0]])
return ans

【Leetcode堆和双端队列】滑动窗口最大值(239)的更多相关文章

  1. python基础教程_学习笔记19:标准库:一些最爱——集合、堆和双端队列

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/36201499 标准库:一些最爱 集合.堆和双端队 ...

  2. lintcode 滑动窗口的最大值(双端队列)

    题目链接:http://www.lintcode.com/zh-cn/problem/sliding-window-maximum/# 滑动窗口的最大值 给出一个可能包含重复的整数数组,和一个大小为  ...

  3. [Leetcode]双项队列解决滑动窗口最大值难题

    这道题是从优先队列的难题里面找到的一个题目.可是解法并不是优先队列,而是双项队列deque 其实只要知道思路,这一道题直接写没有太大的问题.我们看看题 给定一个数组 nums,有一个大小为 k 的滑动 ...

  4. 关于双端队列 deque 模板 && 滑动窗口 (自出)

    嗯... deque 即为双端队列,是c++语言中STL库中提供的一个东西,其功能比队列更强大,可以从队列的头与尾进行操作... 但是它的操作与队列十分相似,详见代码1: 1 #include < ...

  5. 剑指 Offer 59 - I. 滑动窗口的最大值 + 双指针 + 双端队列

    剑指 Offer 59 - I. 滑动窗口的最大值 Offer_59_1 题目详情 方法一:暴力方法+双指针 package com.walegarrett.offer; /** * @Author ...

  6. C#LeetCode刷题之#641-设计循环双端队列(Design Circular Deque)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4132 访问. 设计实现双端队列. 你的实现需要支持以下操作: M ...

  7. Java实现 LeetCode 641 设计循环双端队列(暴力)

    641. 设计循环双端队列 设计实现双端队列. 你的实现需要支持以下操作: MyCircularDeque(k):构造函数,双端队列的大小为k. insertFront():将一个元素添加到双端队列头 ...

  8. LeetCode - 滑动窗口最大值

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 输入: nums ...

  9. Leetcode 239题 滑动窗口最大值(Sliding Window Maximum) Java语言求解

    题目链接 https://leetcode-cn.com/problems/sliding-window-maximum/ 题目内容 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧 ...

随机推荐

  1. WhaleCTF之web-Find me

    WhaleCTF之web-Find me 前往题目 Where is the flag?这是给我提示吗? 没思路,看看源码,说不定有惊喜 哇,在这里啊,得到flag~ flag:{This_is_s0 ...

  2. Python实例3-字符图网格

    假定有一个列表的列表, 内层列表的每个值都是包含一个字符的字符串, 像这样: grid = [['.', '.', '.', '.', '.', '.'], ['.', 'O', 'O', '.', ...

  3. Python学习 备注

    python 3.x中urllib库和urilib2库合并成了urllib库..其中urllib2.urlopen()变成了urllib.request.urlopen() urllib2.Reque ...

  4. KOA 学习(四)

    响应(Response) Koa Response 对象是对 node 的 response 进一步抽象和封装,提供了日常 HTTP 服务器开发中一些有用的功能. response.header Re ...

  5. Redis源码解析:13Redis中的事件驱动机制

    Redis中,处理网络IO时,采用的是事件驱动机制.但它没有使用libevent或者libev这样的库,而是自己实现了一个非常简单明了的事件驱动库ae_event,主要代码仅仅400行左右. 没有选择 ...

  6. 通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账号--锁定次数--菜单功能'menufile

      通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁 ...

  7. php静态变量问题

    <?php$a=0; function test(){ static $a=0; $a+=1; echo $a; }test(); test(); ?>1.static是与销毁时间有关,与 ...

  8. 使用uni-app(Vue.js)创建运行微信小程序项目步骤

    使用uni-app(Vue.js)开发微信小程序项目步骤 1. 新建一个uni-app项目   创建完成后的目录结构 2. 打开微信小程序开发工具端的端口调试功能 3. 运行创建的项目 效果

  9. 抓取B站小视频

    抓取B站小视频的代码如下: #请求库import requests #请求头部信息(用户代理)headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; ...

  10. 【笔记】LR响应时间

    事务:是指在客户端做一种或多种的业务所需要的操作集. 事务响应时间:是通过记录用户请求的开始时间和服务器返回内容到客户时间的差值来计算用户响应时间. 响应时间是服务器返回和用户请求之间的时间差,那么得 ...