华为二面之手撕算法:给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值
话不多说,先上题目
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{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;
}
}
作者:超级鲨鱼辣椒
转载请注明原文链接:https://www.cnblogs.com/jinzlblog/p/15111891.html