规定窗口最大范围容量,持续更新其最大值。
想法:
左右双标,
保证范围大小,用一个双端队列存储,
保证:队列中后面的要比前面的小,却晚到的替代先到的,因为其晚过期。
(后面更新:去除左右双标,减少多余变量,用"i-num+1"来确定)
代码如下:
public static int[] window(int[] arr, int num) {
if (arr.length < 1 || arr == null || num < 1) {
return null;
}
int R = 0;
int[] duan = new int[arr.length];
LinkedList<Integer> max = new LinkedList<Integer>();
for (int i = 0; i < arr.length; i++) {
while (!max.isEmpty() && arr[i] >= arr[max.peekLast()]) {
max.pollLast();
}
max.addLast(i);
duan[i] = arr[max.peekFirst()];
if (max.peekFirst() == i - num + 1) {
max.pollFirst();
}
}
return duan;
}
大神如下,更新:
public static int[] getMaxWindow(int[] arr, int w) {
if (arr == null || w < 1 || arr.length < w) {
return null;
}
LinkedList<Integer> qmax = new LinkedList<Integer>();
int[] res = new int[arr.length - w + 1];
int index = 0;
for (int i = 0; i < arr.length; i++) {
while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i]) {
qmax.pollLast();
}
qmax.addLast(i);
if (qmax.peekFirst() == i - w) {
qmax.pollFirst();
}
if (i >= w - 1) {
res[index++] = arr[qmax.peekFirst()];
}
}
return res;
}
应用如下:
最大值减最小值小于等于arr的子数组数量:
public static int window2(int[] arr, int num) {
if (arr == null || arr.length < num) {
return 0;
}
LinkedList<Integer> max = new LinkedList<Integer>();
LinkedList<Integer> min = new LinkedList<Integer>();
int res = 0;
int i = 0;
int j = 0;
while (i < arr.length) {
while (j < arr.length) {
while (!max.isEmpty() && arr[max.peekLast()] <= arr[j]) {
max.pollLast();
}
max.addLast(j);
while (!min.isEmpty() && arr[min.peekLast()] >= arr[j]) {
min.pollLast();
}
min.addLast(j);
if (arr[max.peekFirst()] - arr[min.peekFirst()] > num) {
break;
}
j++;
}
if (max.peekFirst() == i) {
max.pollFirst();
}
if (min.peekFirst() == i) {
min.pollFirst();
}
res += (j - i);
i++;
}
return res;
}