滑动窗口

给定一个大小为 n≤1e6 的数组。

有一个大小为 k 的滑动窗口,它从数组的最左边移动到最右边。

你只能在窗口中看到 k 个数字。

每次滑动窗口向右移动一个位置。

以下是一个例子:

该数组为 [1 3 -1 -3 5 3 6 7],k 为 3。

窗口位置 最小值 最大值
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3] 5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7

你的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

输入格式

输入包含两行。

第一行包含两个整数 n 和 k,分别代表数组长度和滑动窗口的长度。

第二行有 n个整数,代表数组的具体数值。

同行数据之间用空格隔开。

输出格式

输出包含两个。

第一行输出,从左至右,每个位置滑动窗口中的最小值。

第二行输出,从左至右,每个位置滑动窗口中的最大值。

输入样例:

1
2
8 3
1 3 -1 -3 5 3 6 7

输出样例:

1
2
-1 -3 -3 -3 3 3
3 3 5 5 6 7

个人代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<bits/stdc++.h>
using namespace std;

// 一个降序的单调栈
deque<int> max_stack;
// 一个升序的单调栈
deque<int> min_stack;
int main() {


int n, k;
cin >> n >> k;
vector<int>res1;
vector<int>res2;
vector<int>record(n + 1, 0);

for (int i = 0; i < n; i++) {
cin >> record[i];
while (!max_stack.empty() && record[max_stack.back()] < record[i]) {
max_stack.pop_back();
}
max_stack.push_back(i);

while (!min_stack.empty() && record[min_stack.back()] > record[i]) {
min_stack.pop_back();
}
min_stack.push_back(i);

while (max_stack.front() <= i - k) {
max_stack.pop_front();
}
while (min_stack.front() <= i - k) {
min_stack.pop_front();
}
res1.push_back(max_stack.front());
res2.push_back(min_stack.front());

}
for (int i = k - 1; i < n; i++) {
printf("%d ", record[res2[i]]);
}
cout << endl;
for (int i = k - 1; i < n; i++) {
printf("%d ", record[res1[i]]);
}
}
/*
个人思想: 首先对于一个一个数维护一个双向队列并保证他升序 那么最大的数必然是升序的头元素(ps:在判断是要确定这个元素是否在范围内)如何维护我们趋向于维护一个可能成为最大值的队列如果出现了一个比队列尾部要大的元素自然尾部元素不可能成为最大元素了,需要弹出。

*/

板子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

using namespace std;

const int N = 1000010;

int a[N], q[N];

int main()
{
int n, k;
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);

int hh = 0, tt = -1;
for (int i = 0; i < n; i ++ )
{
if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;

while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
q[ ++ tt] = i;

if (i >= k - 1) printf("%d ", a[q[hh]]);
}

puts("");

hh = 0, tt = -1;
for (int i = 0; i < n; i ++ )
{
if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;

while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
q[ ++ tt] = i;

if (i >= k - 1) printf("%d ", a[q[hh]]);
}

puts("");

return 0;
}