数据结构入门-单调队列
原理介绍
双向队列
思考一下:对于数组nums
,我们想知道max(nums[i-k],...,nums[i])
如何高效处理?
单调队列
单调队列,即从队首到队尾单调的队列。
假设nums = [10,8,6,4,5,12],k=2
,单调队列滑动窗口入队出队过程:
需要注意的是在滑动窗口时,我们需要知道原数据节点的下标,所以需要以二元组绑定索引值的形式处理。这种情况下,队首始终是最大值,并满足从队首到队尾单调递减。
例题练习
力扣 239. 滑动窗口最大值
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] ans = new int[n-k+1];
Deque<Integer[]> ql = new ArrayDeque<Integer[]>();
for (int i = 0; i < n; i++) {
while (!ql.isEmpty() && i-ql.peekFirst()[0] >= k) ql.pollFirst();
Integer[] t = {i, nums[i]};
while (!ql.isEmpty() && ql.peekLast()[1] < nums[i]) ql.pollLast();
ql.offerLast(t);
if (i-k+1 >= 0) ans[i-k+1] = ql.peekFirst()[1];
}
return ans;
}
}
P1886 滑动窗口 /【模板】单调队列
70分~,这道题还是建议使用C++,否则很容易内存超出(MLE)或者时间超出(TLE)。
import java.io.*;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
public class Main {
static int[] minSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] ans = new int[n-k+1];
Deque<Integer[]> ql = new ArrayDeque<Integer[]>();
for (int i = 0; i < n; i++) {
while (!ql.isEmpty() && i-ql.peekFirst()[0] >= k) ql.pollFirst();
Integer[] t = {i, nums[i]};
while (!ql.isEmpty() && ql.peekLast()[1] > nums[i]) ql.pollLast();
ql.offerLast(t);
if (i-k+1 >= 0) ans[i-k+1] = ql.peekFirst()[1];
}
return ans;
}
static int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] ans = new int[n-k+1];
Deque<Integer[]> ql = new ArrayDeque<Integer[]>();
for (int i = 0; i < n; i++) {
while (!ql.isEmpty() && i-ql.peekFirst()[0] >= k) ql.pollFirst();
Integer[] t = {i, nums[i]};
while (!ql.isEmpty() && ql.peekLast()[1] < nums[i]) ql.pollLast();
ql.offerLast(t);
if (i-k+1 >= 0) ans[i-k+1] = ql.peekFirst()[1];
}
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int n = sc.nextInt();
int k = sc.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
int[] ans1 = minSlidingWindow(nums, k);
int[] ans2 = maxSlidingWindow(nums, k);
for (int i = 0; i < n-k+1; i++) {
out.print(ans1[i]);
if (i != n-k) out.print(" ");
}
out.println();
out.flush();
for (int i = 0; i < n-k+1; i++) {
out.print(ans2[i]);
if (i != n-k) out.print(" ");
}
out.flush();
}
}