标签:下标 nums int 双端 LeetCode 过期 Window 数组 Sliding
作者:Grey
原文地址:LeetCode 239. Sliding Window Maximum
题目描述
思路
数组为num, 滑动窗口大小是k,首先两个极端情况:
-
如果k=1,则直接返回原数组即可(滑动窗口大小为1,那么每个窗口的最小值/最大值就是其本身)
-
如果k == num.length, 那么返回一个数组大小为1的数组,这个数组里面的唯一的数就是整个数组的最大值
然后讨论普遍情况: 1 < k < num.length
如果窗口大小为k,数组长度为n,那么滑动窗口最大值数组的长度通过观察可知, 结果数组的长度为:
n - k + 1
接着,我们定义一个双端队列,这个双端队列存的是数组下标,且下标对应的原元素头到尾部数据是从大到小的
我们定义一个r变量来遍历数组, 整个流程分为如下三步:
-
nums[r]
的数据和双端队列尾部下标(假设是inx)对应的数据元素数据,即nums[inx]
, 进行比较,如果nums[inx]
小于nums[r]
则,双端队列把尾部的inx值弹出
继续比较双端队列尾部的对应的数组值和nums[r]
的大小,直到num[r]<num[双端队列尾部存的下标值]
。 -
当双端队列头部的元素==r-k时候,说明双端队列头部的元素需要被淘汰了,双端队列中头部的值已经过期下标了,需要弹出这个过期下标 比如:窗口k为3
- r来到3位置,那么过期下标就是0
- r来到4位置,那么过期下标就是1
- r来到5位置,那么过期下标就是2
- r来到6位置,那么过期下标就是3
- r来到7位置,那么过期下标就是4 …
-
当
r>=k-1
的时候,说明窗口已经形成了,此时,每次进入一个数,就要收集一次答案。
完整代码
public static int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
if (k == 1) {
return nums;
}
if (k == n) {
return new int[]{maxOfArr(nums, n)};
}
// 数组长度是n,窗口是k,则结果数组长度为n - k + 1
int[] ans = new int[n - k + 1];
// 头部进,尾部出
// 从头到尾依次从大到小
LinkedList<Integer> qMax = new LinkedList<>();
int r = 0;
int index = 0;
while (r < n) {
while (!qMax.isEmpty() && nums[qMax.peekLast()] <= nums[r]) {
// 给nums[r] 腾出位置
qMax.pollLast();
}
// 现在qMax尾部的值一定大于r
// 所以可以放心的把r加入到尾部中去
qMax.addLast(r);
// 如果此时双端队列中头部的值是过期下标
// 比如r来到3位置,窗口k为3,那么过期下标就是0
// 比如r来到4位置,窗口k为3,那么过期下标就是1
// 比如r来到5位置,窗口k为3,那么过期下标就是2
// 比如r来到6位置,窗口k为3,那么过期下标就是3
// 比如r来到7位置,窗口k为3,那么过期下标就是4
// ...
if (qMax.peekFirst() == r - k) {
// 弹出过期下标
qMax.pollFirst();
}
// 窗口形成了,每次加入一个数收集一个答案
if (r >= k - 1) {
ans[index++] = nums[qMax.peekFirst()];
}
r++;
}
return ans;
}
private static int maxOfArr(int[] nums, int n) {
int max = nums[0];
for (int i = 1; i < n; i++) {
max = Math.max(max, nums[i]);
}
return max;
}
更多
标签:下标,nums,int,双端,LeetCode,过期,Window,数组,Sliding 来源: https://blog.csdn.net/hotonyhui/article/details/121735852
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。