文章目录
- 题目:
- 解法1:暴力
- 解法2:双端队列
- 解法3:大顶堆
题目:
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。
进阶:
你能在线性时间复杂度内解决此题吗?
示例:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13输入: 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
提示:
- 1 <= nums.length <= 10^5
- -10^4 <= nums[i] <= 10^4
- 1 <= k <= nums.length
解法1:暴力
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24/** * 思路: * 比较k范围内的值,找到并记录 * 如果当前的max等于start-1,前移的时候就重新从start到end找max。 * 如果不等于,直接比较max和end */ public int[] maxSlidingWindow(int[] nums, int k) { int start=0,end=k-1,max=nums[0]; int[] result=new int[nums.length-k+1]; while (end<nums.length){ if (start==0||max == nums[start-1]){ max=nums[start]; for (int i=start;i<=end;i++){ max=Math.max(max,nums[i]); } }else { max=Math.max(max,nums[end]); } result[start++]=max; end++; } return result; }
时间复杂度:On^2
空间复杂度:On
解法2:双端队列
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31/** * 思路: * 双端队列实现 * 每进来一个数前,先要和前面的数进行比较,如果当前的数比前面的数大,就进行出队操作 * 判断当前的队列头部的元素下标有没有超出窗口范围 * 在队列的尾部加入元素 * 如果达到了窗口的长度,就进行一次最大值的记录 */ public int[] maxSlidingWindow(int[] nums, int k) { ArrayDeque<Integer> queue = new ArrayDeque<>(); int[] result = new int[nums.length-k+1]; int index=0; for (int i = 0; i < nums.length; i++) { while (!queue.isEmpty() && nums[i] > nums[queue.peekLast()]) { queue.pollLast(); } while (!queue.isEmpty() &&queue.peek()<i-k+1){ queue.pollFirst(); } queue.offerLast(i); if (i>=k-1){ result[index++]=nums[queue.peek()]; } } return result; }
时间复杂度:On^2
空间复杂度:On
解法3:大顶堆
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/** * 思路: * 大顶堆 * 移除超出窗口范围的值 * 如果到达窗口边界就记录一次最大值 */ public int[] maxSlidingWindow(int[] nums, int k) { PriorityQueue<Integer> heap = new PriorityQueue<>((v1, v2) -> v2 - v1); int[] result = new int[nums.length - k + 1]; int index=0; for (int i=0;i<nums.length;i++){ if (i>=k)heap.remove(nums[i-k]); heap.offer(nums[i]); if (i>=k-1){ result[index++]=heap.peek(); } } return result; }
时间复杂度:On^2logn
空间复杂度:On
如果不理解堆的构造函数
PriorityQueue<Integer> heap = new PriorityQueue<>((v1, v2) -> v2 - v1);
可以看我的这篇文章:Prioprity源码分析–priority如何实现优先级排序?
最后
以上就是洁净路灯最近收集整理的关于239. 滑动窗口最大值(java实现)--LeetCode的全部内容,更多相关239.内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复