算法1
常规思路就是依次求每个滑动窗口的最大值保存即可
这样做每个窗口都需要求K个数的最大值,我们可以优化一下减少计算量
如果窗口往右滑动,新加入的数>=前一个窗口的最大值,那么显然不用再重复计算该窗口的最大值,因为就是这个新加入的数,如果小于前一个窗口的最大值,那么只要窗口还没滑过那个最大值,则当前窗口的最大值还是它。
java 代码
public int[] maxInWindows(int[] nums, int k) {
if (nums == null || nums.length == 0 || k <= 0)
return nums; //输入非法,直接返回nums
int n = nums.length + 1 - k; //滑动窗口的数量
int[] res = new int[n]; //用来保存每个滑动窗口的最大值
res[0] = getMax(nums, 0, k)[0]; //先计算并保存第一个滑动窗口的最大值,这一步计算无论如何都省不掉的
int curPos = getMax(nums, 0, k)[1]; //用来记录当前窗口最大值的位置
for (int i = 1; i < n; i++) { //接下来求剩余窗口的最大值并填充到res中
if (nums[i + k - 1] >= res[i - 1]) { //如果下一个数>=前一个窗口的最大值就直接填充它即可
res[i] = nums[i + k - 1];
curPos = i + k -1; //更新当前窗口最大值的位置
}
else if (i <= curPos) res[i] = nums[curPos]; //如果比最大值小,只要窗口还没滑出curPos,当前窗口的最大值还是它
else {
res[i] = getMax(nums, i, k)[0]; //否则的话就只能重新计算当前窗口最大值了
curPos = getMax(nums, i, k)[1];
}
}
return res;
}
//用来计算从index ~ index + k - 1这个窗口的最大值,返回最大值及其位置
private int[] getMax(int[] nums, int index, int k) {
int max = Integer.MIN_VALUE;
int pos = -1;
for (int i = index; i < index + k; i++)
if (nums[i] > max) {
max = nums[i];
pos = i;
}
return new int[]{max, pos};
}
nb