239 滑动窗口最大值
直接实现
思路:此题分为两种情况,
- k == length:直接求最大数
- k < length :用for循环继续遍历判断对第 k + 1个以及之后元素取最大值
但此方法时间复杂度O(n * k2)较大,对大量数据Timeout
public int[] maxSlidingWindow(int[] nums, int k) {
int[] result = new int[nums.length - k + 1];
// 长度等于k的
if (nums.length == k) {
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
max = Math.max(max, nums[i]);
}
result[0] = max;
}
// 长度大于k的
else {
Queue<Integer> queue = new LinkedList<>();
// k个元素先进队列
for (int i = 0; i < k; i++) {
queue.add(nums[i]);
int max = -Integer.MAX_VALUE - 1;
for (Integer num : queue) {
max = Math.max(max, num);
}
result[0] = max;
}
// 判断大小,并将max插入到result数组
for (int i = k; i <= nums.length - 1; i++) {
// 出队进队
queue.poll();
queue.add(nums[i]);
// 选最大的
int max = -Integer.MAX_VALUE - 1;
for (Integer num : queue) {
max = Math.max(max, num);
}
result[i - k + 1] = max;
}
}
return result;
}
二次优化
对队列进行优化
- 出队:遍历数组s后面的元素,只有出队元素是最大值时才出队
- 进队:在出口处把小于进队元素的出队,再进队
- 获取最大值(也是获取出队口第一个值):由于实现了单调数组,因此第一个数则为最大值
优点:去掉了不必维护的数,节省了时间复杂度 O(n)
class MyQueue{
Deque<Integer> deque = new LinkedList<>();
/**
* 出队
* @param val
*/
void poll(int val){
// 判空以及判断弹出值是否为最大值,相等则弹出
if (!deque.isEmpty() && val == deque.peek()){
deque.poll();
}
}
/**
* 入队
* @param val
*/
void add(int val){
// 判空且如果入口处元素比入队元素小则弹出 - 保证队列元素单调递减(小的元素不需要维护)
// 注意:此时不是严格的队列,是一个在出口和入口都能插入删除的特殊队列
while (!deque.isEmpty() && val > deque.getLast()){
deque.remove