话不多说,先上题目
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{2,3,4,2,6,2,5,1}
及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}
;
针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个:
{[2,3,4],2,6,2,5,1}
, {2,[3,4,2],6,2,5,1}
, {2,3,[4,2,6],2,5,1}
, {2,3,4,[2,6,2],5,1}
, {2,3,4,2,[6,2,5],1}
, {2,3,4,2,6,[2,5,1]}
。
窗口大于数组长度的时候,返回空。
样例:
输入:[2,3,4,2,6,2,5,1],3
输出:[4,4,6,6,6,5]
方法一
话不多说,上代码
class Solution { public int[] allmax(int[] arr, int target) { // 滑动窗口大小大于数组长度,返回空 if (i > arr.length) { return null; } // 计算出滑动窗口的个数 int[] r = new int[arr.length - i + 1]; // 用于保存滑动窗口的最大值 int max = 0; // 滑动窗口的头指针 int f = 0; // 滑动窗口的尾指针 int s = f + i -1; // 循环,直到尾指针到达数组尾部 while (s < arr.length) { // 使用冒泡算法计算出当前滑动窗口里的最大值 for (int j = f; j <= s; j++) { if (arr[j] > max) { max = arr[j]; } } // 保存到结果数组 r[f] = max; // 将最大值重置 max = 0; // 头指针向后移动 f++; // 尾指针向后移动 s++; } return r; } }
临时写出来的一个使用双指针移动的方法,这种方法的时间复杂度为
O=窗口个数*窗口大小
,存在重复比较的问题
方法二
话不多说,再上代码
class Solution { public int[] allmax(int[] nums, int k) { if(nums == null || nums.length == 0) { return new int[0]; } int[] res = new int[nums.length - k + 1]; Deque<Integer> queue = new ArrayDeque<>(); for(int i = 0, j = 0; i < nums.length; i++) { if(!queue.isEmpty() && i - queue.peek() >= k) { queue.poll(); } while(!queue.isEmpty() && nums[i] > nums[queue.peekLast()]) { queue.pollLast(); } queue.offer(i); if(i >= k - 1) { res[j++] = nums[queue.peek()]; } } return res; } }