Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.

Example:

Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
Output: [3,3,5,5,6,7]
Explanation:

Window position Max
--------------- -----
[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

Note: 
You may assume k is always valid, 1 ≤ k ≤ input array's size for non-empty array.

Follow up:
Could you solve it in linear time?

思路

咋一看不知道题目要干嘛,其实求的是窗口从左往右滑动过程中,返回窗口中元素的最大值。比如上面Max的那一列是 3 3 5 5 6 7,那么返回的就是这个。

感觉直接遍历好像就可以了诶,不过应该会超时。而且提示我们用O(n)复杂度内解题了,看了下别人的解法,使用的是双向队列deque,保存数组元素的索引,遍历整个数组。

We scan the array from 0 to n-1, keep "promising" elements in the deque. The algorithm is amortized O(n) as each element is put and polled once.

At each i, we keep "promising" elements, which are potentially max number in window [i-(k-1),i] or any subsequent window. This means

  1. If an element in the deque and it is out of i-(k-1), we discard them. We just need to poll from the head, as we are using a deque and elements are ordered as the sequence in the array

  2. Now only those elements within [i-(k-1),i] are in the deque. We then discard elements smaller than a[i] from the tail. This is because if a[x] <a[i] and x<i, then a[x] has no chance to be the "max" in [i-(k-1),i], or any other subsequent window: a[i] would always be a better candidate.

  3. As a result elements in the deque are ordered in both sequence in array and their value. At each step the head of the deque is the max element in [i-(k-1),i]

对于每个索引i位置,它都有可能是窗口[i-(k-1),i]中的那个最大值,以题目中的例子来说明,假如i=4, 那么窗口[2, 4],即索引 2,3,4位置构成的窗口。位置4可能是这个窗口中的最大值,或者是后面窗口的最大值(因为向右滑动时还包含在里面)。这表明:

1. 如果当前队列中的索引不在窗口[2, 4]的范围内,那么丢弃它。

2. 如果现在队列中的索引只有当前窗口里面[i-(k-1),i]的,那么从尾部开始丢弃掉比a[i]小的元素,这是因为如果 a[x]<a[i] 并且 x<i,那么a[x] 不可能是 [i-(k-1), i] 中的最大值,并且在后面的窗口中也不可能是最大的,因为a[i]是更好的选择。(因为当前的索引,也就是从 i-(k-1)到i都被限制在一个窗口里了)

3. 因为每次的滑动窗口所选择的出的最大元素在队列中是按照他们的数组索引和值排序的,所以每一不这个deque的头就是 [i-(k-1),i] 中的最大元素。

代码

public int[] maxSlidingWindow(int[] a, int k) {
if (a == null || k <= 0) {
return new int[0];
}
int n = a.length;
int[] r = new int[n-k+1];
int ri = 0;
// store index
Deque<Integer> q = new ArrayDeque<>(); //双端队列的用法
for (int i = 0; i < a.length; i++) {
// 将不在当前窗口 i-k+1 到 i 内的索引移除
while (!q.isEmpty() && q.peek() < i - k + 1) {
q.poll(); // 弹出队列中的第一元素(头部,最左边)
}
// 从尾部(队列右边)remove smaller numbers in k range as they are useless
while (!q.isEmpty() && a[q.peekLast()] < a[i]) {
q.pollLast();
}
// q contains index... r contains content
q.offer(i);
if (i >= k - 1) {  // 只需要判断i-k+1>0即可,因为只有一开始不够k个元素
r[ri++] = a[q.peek()]; // 经过上面处理,队头是当前窗口中的最大元素
}
}
return r;
}

LeetCode239. Sliding Window Maximum的更多相关文章

  1. leetcode面试准备:Sliding Window Maximum

    leetcode面试准备:Sliding Window Maximum 1 题目 Given an array nums, there is a sliding window of size k wh ...

  2. 【LeetCode】239. Sliding Window Maximum

    Sliding Window Maximum   Given an array nums, there is a sliding window of size k which is moving fr ...

  3. 【刷题-LeetCode】239. Sliding Window Maximum

    Sliding Window Maximum Given an array nums, there is a sliding window of size k which is moving from ...

  4. [Swift]LeetCode239. 滑动窗口最大值 | Sliding Window Maximum

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...

  5. Sliding Window Maximum 解答

    Question Given an array of n integer with duplicate number, and a moving window(size k), move the wi ...

  6. Sliding Window Maximum

    (http://leetcode.com/2011/01/sliding-window-maximum.html) A long array A[] is given to you. There is ...

  7. Sliding Window Maximum LT239

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...

  8. LeetCode题解-----Sliding Window Maximum

    题目描述: Given an array nums, there is a sliding window of size k which is moving from the very left of ...

  9. [LeetCode] Sliding Window Maximum 滑动窗口最大值

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...

随机推荐

  1. Linux用户、用户组权限管理详解 --- 02

    2,用户.用户组管理操作详解: 2.1 adduser 添加用户: adduser [-u uid][-g group][-d home][-s shell] -u:直接给出userID        ...

  2. Codeforces Round #511 (Div. 2):C. Enlarge GCD(数学)

    C. Enlarge GCD 题目链接:https://codeforces.com/contest/1047/problem/C 题意: 给出n个数,然后你可以移除一些数.现在要求你移除最少的数,让 ...

  3. HDU5154拓扑排序

    Harry and Magical Computer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  4. Spring------mysql读写分离

    1. 为什么要进行读写分离 大量的JavaWeb应用做的是IO密集型任务, 数据库的压力较大, 需要分流 大量的应用场景, 是读多写少, 数据库读取的压力更大 一个很自然的思路是使用一主多从的数据库集 ...

  5. Anaconda创建python(2.7/3.6)的虚拟环境后需要添加ipykernel

    今天在工作的过程中遇到这样一个问题:安装完Anaconda利用conda创建了虚拟环境,但是启动jupyter notebook之后却找不到虚拟环境中的python kernel.后来上网找到了解决办 ...

  6. ExtJS下拉列表使用方法(异步传输数据)

    最近使用ExtJS下拉列表框(ComboBox)希望完成一个动态下拉列表的功能,即列表中的数据都通过异步方式查询数据库而来,同时在用户选择了列表中的某个值后,可以从后台正确的获取用户选择项所对应的值. ...

  7. MSSQL,MySQL 语法区别

    1 mysql支持enum,和set类型,sql server不支持 2 mysql不支持nchar,nvarchar,ntext类型 3 mysql的递增语句是AUTO_INCREMENT,而mss ...

  8. 南阳ACM 题目517:最小公倍数 Java版

    最小公倍数 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 为什么1小时有60分钟,而不是100分钟呢?这是历史上的习惯导致. 但也并非纯粹的偶然:60是个优秀的数字,它 ...

  9. 数据结构&图论:图

    在这里对图的存储和遍历进行一个规范,为以后更复杂的数据结构学习打下基础 首先是邻接矩阵的形式,适合于存稠密图,如果是全连接图就再合适不过了 int a[maxn][maxn]; 一个二维数组就可以搞定 ...

  10. btrace 常见问题

    执行btrace命令报错:Unable to open socket file: target process not responding or HotSpot VM not loaded ---- ...