mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-12-01 00:08:53 +00:00
109 lines
5.2 KiB
Java
109 lines
5.2 KiB
Java
> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
|
||
>
|
||
> 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。
|
||
>
|
||
> 另外希望手机阅读的同学可以来我的 <u>[**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入。
|
||
|
||
#### [剑指 Offer 59 - I. 滑动窗口的最大值](https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/)
|
||
|
||
这个题目,算是很经典的类型,我们的滑动窗口主要分为两种,一种的可变长度的滑动窗口,一种是固定长度的滑动窗口,这个题目算是固定长度的代表。今天我们用双端队列来解决我们这个题目,学会了这个题目的解题思想你可以去解决一下两道题目 [剑指 Offer 59 - II. 队列的最大值](https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/),[155. 最小栈](https://leetcode-cn.com/problems/min-stack/),虽然这两个题目和该题类型不同,但是解题思路是一致的,都是很不错的题目,我认为做题,那些考察的很细的,解题思路很难想,即使想到,也不容易完全写出来的题目,才是能够大大提高我们编码能力的题目,希望能和大家一起进步。
|
||
|
||
这个题目我们用到了**双端队列**,队列里面保存的则为每段滑动窗口的最大值,我给大家做了一个动图,先来看一下代码执行过程吧。
|
||
|
||
我们先来了解下双端队列吧,队列我们都知道,是先进先出,双端队列呢?既可以从队头出队,也可以从队尾出队,则不用遵循先进先出的规则。
|
||
|
||
下面我们通过一个动图来了解一下吧。
|
||
|
||
![](https://img-blog.csdnimg.cn/20210319154950406.gif)
|
||
|
||
好啦,我们了解双端队列是什么东东了,下面我们通过一个动画,来看一下代码的执行过程吧,相信各位一下就能够理解啦。
|
||
|
||
我们就通过题目中的例子来表述。nums = [1,3,-1,-3,5,3,6,7], k = 3
|
||
|
||
![](https://img-blog.csdnimg.cn/20210319162114967.gif)
|
||
|
||
不知道通过上面的例子能不能给各位描述清楚,如果不能的话,我再加把劲,各位看官,请接着往下看。
|
||
|
||
我们将执行过程进行拆解。
|
||
|
||
1.想将我们第一个窗口的所有值存入单调双端队列中,单调队列里面的值为单调递减的。如果发现队尾元素小于要加入的元素,则将队尾元素出队,直到队尾元素大于新元素时,再让新元素入队,目的就是维护一个单调递减的队列。
|
||
|
||
2.我们将第一个窗口的所有值,按照单调队列的规则入队之后,因为队列为单调递减,所以队头元素必为当前窗口的最大值,则将队头元素添加到数组中。
|
||
|
||
3.移动窗口,判断当前**窗口前的元素**是否和队头元素相等,如果相等则出队。
|
||
|
||
4.继续然后按照规则进行入队,维护单调递减队列。
|
||
|
||
5.每次将队头元素存到返回数组里。
|
||
|
||
5.返回数组
|
||
|
||
是不是懂啦,再回去看一遍视频吧。祝大家新年快乐,天天开心呀!
|
||
|
||
```java
|
||
class Solution {
|
||
public int[] maxSlidingWindow(int[] nums, int k) {
|
||
int len = nums.length;
|
||
if (len == 0) {
|
||
return nums;
|
||
}
|
||
int[] arr = new int[len - k + 1];
|
||
int arr_index = 0;
|
||
//我们需要维护一个单调递增的双向队列
|
||
Deque<Integer> deque = new LinkedList<>();
|
||
for (int i = 0; i < k; i++) {
|
||
while (!deque.isEmpty() && deque.peekLast() < nums[i]) {
|
||
deque.removeLast();
|
||
}
|
||
deque.offerLast(nums[i]);
|
||
}
|
||
arr[arr_index++] = deque.peekFirst();
|
||
for (int j = k; j < len; j++) {
|
||
if (nums[j - k] == deque.peekFirst()) {
|
||
deque.removeFirst();
|
||
}
|
||
while (!deque.isEmpty() && deque.peekLast() < nums[j]) {
|
||
deque.removeLast();
|
||
}
|
||
deque.offerLast(nums[j]);
|
||
arr[arr_index++] = deque.peekFirst();
|
||
}
|
||
return arr;
|
||
}
|
||
}
|
||
```
|
||
|
||
GO Code:
|
||
|
||
```go
|
||
func maxSlidingWindow(nums []int, k int) []int {
|
||
l := len(nums)
|
||
if l == 0 {
|
||
return nums
|
||
}
|
||
|
||
arr := []int{}
|
||
// 维护一个单调递减的双向队列
|
||
deque := []int{}
|
||
for i := 0; i < k; i++ {
|
||
for len(deque) != 0 && deque[len(deque) - 1] < nums[i] {
|
||
deque = deque[:len(deque) - 1]
|
||
}
|
||
deque = append(deque, nums[i])
|
||
}
|
||
|
||
arr = append(arr, deque[0])
|
||
for i := k; i < l; i++ {
|
||
if nums[i - k] == deque[0] {
|
||
deque = deque[1:]
|
||
}
|
||
for len(deque) != 0 && deque[len(deque) - 1] < nums[i] {
|
||
deque = deque[:len(deque) - 1]
|
||
}
|
||
deque = append(deque, nums[i])
|
||
arr = append(arr, deque[0])
|
||
}
|
||
return arr
|
||
}
|
||
```
|