双指针(时间复杂度从O(nk))
其实已经优化了,但还是有缺陷,因为找最大值得过程就得遍历k个数据
class Solution {
public ArrayList<Integer> maxInWindows(int[] num, int size) {
ArrayList<Integer> res = new ArrayList<Integer>();
if (size == 0) return res;
int left = 0;
int right = size - 1;
int maxIndex = 0;
int max = Integer.MIN_VALUE;
while (right < num.length) {
if (num[right] > max || left > maxIndex) {
max = num[left];
for (int i = left; i <= right; ++i) {
if (num[i] >= max) {
max = num[i];
maxIndex = i;
}
}
}
res.add(max);
left++;
right++;
}
return res;
}
}
双端队列Deque
-
初始化窗口,最大值存在队列里面,初始化只有一个。从后面比较,然后从后面进,这样能保证递减和头元素最大
-
开始一次遍历循环即可
-
一定要先判断这个头部元素是不是前一个窗口的值,如果是的话就删了。
-
之后dq等于空直接加,不等于空->每次只比队列中的最后一个,比新值小的都删了,反正到这里了,前面的都没用了。
-
取第一个值放到res里面即可。
-
就记住一点从后面比是保证递减
取最大值从头部取
public class Solution {
public ArrayList<Integer> maxInWindows(int[] num, int size) {
ArrayList<Integer> res = new ArrayList<Integer>();
//做一个非严格递减的双端队列,头部最大
//+1后遇到更大的,删除前面所有,因为没有意义了。
ArrayDeque<Integer> dq = new ArrayDeque<Integer>();
if (size == 0) return res;
//先形成窗口
for (int i = 0; i < size; i++) {
while (!dq.isEmpty() && num[i] > dq.peekLast()) {
dq.removeLast();//全部删除直到等于空位置,非严格递减。
}
dq.add(num[i]);
}
res.add(dq.peekFirst());
//后一次遍历即可
for (int i = size; i < num.length; i++) {
if (num[i-size]==dq.peekFirst()) dq.removeFirst();
while (!dq.isEmpty() && num[i] > dq.peekLast()) {
dq.removeLast();
}
dq.addLast(num[i]);
res.add(dq.peekFirst());
}
return res;
}
}