力扣239. 滑动窗口最大值

下面我们来看一道滑动窗口的题目

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

返回 滑动窗口中的最大值

示例 1:

复制代码
输入: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

示例 2:

复制代码
输入:nums = [1], k = 1
输出:[1]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

分析一下这道题目:

首先我们来想一个简单的思路,就是使用一个切片去维护一个窗口,每次窗口移动了,就重新遍历一遍这个窗口去求最大值,那么对于一个大小为n的数组维护一个长度为k的窗口,他的时间复杂度就是O(n × k),对于这一道题目时间复杂度还是很高的,我尝试了用这种方法,果然是超时了!

思路优化:

1.取出比新元素还小的元素:

首先我们可以想到,对于一个新添加进入的元素来说,如果他比原来的元素还大,那么原来的元素不可能成为最大的值,所以可以让新添加的元素去和已经存在的元素比较,已存在较小的元素出队!

2.新的队列会形成一个有序队列:

按照刚才说的,那么如果前面有小的元素,那么他一定被取出了,如果前面有大的元素一定不会取出,那么这就形成了一个从大到小的有序队列。

3.使用双端队列:

对于队尾的元素,需要比新元素小的需要出队,那么对于队头来说,超过当前滑动窗口的范围也需要出队!并且新元素需要在队尾入队,前后都可以出队和入队!这就相当于是一个双端队列!

4.使用切片模拟双端队列:

go语言原生是没有双端队列的,所以需要我们使用切片模拟,我们可以使用arr:n和arr1:来进行入队和出队的模拟,那么切片本身就相当于一个队列窗口了!

答案以及解析

package main

func maxSlidingWindow(nums \[\]int, k int) \[\]int {

// 先判断是否为空的情况

if len(nums) == 0 || k == 0 {

return \[\]int{}

}

// 用来存答案

ans := make(\[\]int, 0)

// 用来存元素的下标,模拟双端队列

win := make(\[\]int, 0)

for i, x := range nums {

// 1. 移除滑出当前窗口的队头下标

if len(win) > 0 && win0 < i-k+1 {

win = win1:

}

// 2. 维护单调性:弹出所有小于当前值 x 的队尾下标

for len(win) > 0 && numswin\[len(win)-1] <= x {

win = win:len(win)-1

}

// 3. 当前下标入队

win = append(win, i)

// 4. 窗口形成后,队头永远是当前窗口最大值的下标

if i >= k-1 {

ans = append(ans, numswin\[0])

}

}

return ans

}

总结:

这里需要注意几点:

1.因为这个队列只有进出操作,没有排序操作,所以队列最左边的一定是我们之前最早进入的元素,而队列右边一定是我们最后进入的元素,判断元素过期的时候我们就需要比较最左边元素是否过期。

2.我们还需要知道一些特殊的操作,除去队列队头元素(win=win1:),除去队列队尾的元素(win=win:len(win)),向队尾添加元素(win=append(win,i))

相关推荐
find1star14 分钟前
LeetCode 141:环形链表
java·算法·leetcode·链表
迅翼SwiftWing21 分钟前
编队系列(总)|固定翼编队如何实现稳定飞行?通信架构、协同算法与工程约束深度解析
算法·架构
LB211231 分钟前
力扣160 21 86
算法·leetcode·职场和发展
爱学堂IT分享1 小时前
鹤翔老师pmp项目管理培训认证考试课 (直播录播题库送学时证明)【共58课时】-51CTO学堂
后端
王的宝库1 小时前
Go 项目结构:从单文件到标准工程布局
开发语言·后端·golang
小智老师PMP2 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
HugoStudio_SWAN2 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
a187927218312 小时前
【算法】动态规划第二篇:双序列 DP 三课——继承、计步与断链
算法·leetcode·动态规划·dp·回溯·暴力·算法讲解
码事漫谈2 小时前
类型即世界:一个 C++ 程序员的本体论入门
后端
Rain的Java大神之路3 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发