滑动窗口算法是一种处理序列数据(如数组、字符串等)的高效方法,它通过在数据上移动一个固定大小的窗口,并在每个窗口位置上执行特定的操作来解决问题。滑动窗口算法的原理和操作步骤如下:
算法原理
-
窗口初始化:定义一个长度固定的窗口,这个窗口在序列的起始位置开始。
-
窗口操作:对当前窗口内的元素执行所需的操作,这可能包括计算和、最大值、最小值、计数等。
-
窗口滑动:将窗口向前移动一位,通常是向右移动一个元素。这可以通过简单地扩展窗口的右边界并缩小左边界来实现。
-
重复操作:重复步骤2和3,直到窗口的右边界到达序列的末尾。
-
结果输出:在每次窗口移动后,根据需要输出结果,或者在窗口移动完成后输出最终结果。
操作步骤
-
确定窗口大小:根据问题的需求确定窗口的大小。窗口大小可能是固定的,也可能是根据某些条件动态变化的。
-
初始化数据结构:创建用于存储窗口边界、临时结果等的数据结构。
-
执行窗口内操作:对当前窗口内的元素执行操作,如计算窗口内元素的和、找到窗口内的最大/最小值等。
-
更新窗口:根据滑动窗口算法的类型(例如,增加窗口的右边界、减少窗口的左边界等),更新窗口的位置。
-
处理边界情况:在窗口移动过程中,需要注意边界情况,如窗口左边界超出序列起始位置或右边界超出序列末尾位置。
-
记录结果:在每次窗口移动后,记录或输出当前窗口的操作结果。
-
结束条件:当窗口的右边界到达序列末尾时,算法结束。
滑动窗口算法在很多问题中都非常有用,例如计算连续子数组的最大和、找到无重复字符的最长子串、解决矩阵中的最小路径和问题等。通过在序列上滑动窗口并执行操作,我们可以在一次遍历中解决问题,避免了多次遍历序列的开销,从而提高了算法的效率。
问题:
给定一个长度不超过10^6的数组,你需要找到一个大小为m的滑动窗口,这个窗口会从数组的最左端滑动到最右端,每次只向右移动一个位置。在窗口的每次移动中,你只能看到窗口内的k个数字。目标是找出在每次移动过程中,这m个数字的某种特定属性(最小值、最大值),并对这些属性进行记录或输出。
输入格式
- 第一行包含两个整数
n
和k
,用空格隔开。n
是数组的长度。k
是滑动窗口的长度。
- 第二行包含
n
个整数,这些整数用空格隔开,代表数组的具体数值。
输出格式
- 输出分为两行。
- 第一行:从左至右,输出每个位置滑动窗口中的最小值。
- 第二行:从左至右,输出每个位置滑动窗口中的最大值。
示例
输入样例:
10 3
5 1 4 2 8 7 3 1 5 9
输出样例:
1 1 2 2 3 1 1 1
5 4 8 8 8 7 5 9
代码:
#include<iostream> // 引入标准输入输出库
using namespace std; // 使用标准命名空间
const int N = 1000010; // 定义常量N,表示数组的最大容量
int a[N], q[N]; // 定义两个数组a和q,分别用于存储输入的数组和辅助数组
int main()
{
int n, m; // 定义变量n和m,分别表示数组a的长度和窗口大小
cin >> n >> m; // 从标准输入读取n和m的值
for(int i = 0; i < n; i ++) // 循环读取n个整数到数组a中
cin >> a[i];
int hh = 0, tt = -1; // 定义两个指针hh和tt,分别表示q数组的头部和尾部
// 第一部分:找出位于最小值之间的元素并输出
for(int i = 0; i < n; i ++)
{
// 如果当前位置减去q数组头部位置大于窗口大小m,则移动头部指针
if(i - q[hh] + 1 > m ) hh ++;
// 移除q数组尾部比当前元素大的所有元素
while(hh <= tt && a[i] < a[q[tt]])
tt --;
// 将当前元素的位置i添加到q数组尾部
q[++ tt] = i;
// 如果当前位置加上1等于或超过窗口大小m,则输出q数组头部的元素
if(i + 1 >= m)
cout << a[q[hh]] << " ";
}
puts(""); // 输出换行符
// 重置指针hh和tt
hh = 0, tt = -1;
// 第二部分:找出位于最大值之间的元素并输出
for(int i = 0; i < n; i ++)
{
// 如果当前位置减去q数组头部位置大于窗口大小m,则移动头部指针
if(i - q[hh] + 1 > m ) hh ++;
// 移除q数组尾部比当前元素小的所有元素
while(hh <= tt && a[i] > a[q[tt]])
tt --;
// 将当前元素的位置i添加到q数组尾部
q[++ tt] = i;
// 如果当前位置加上1等于或超过窗口大小m,则输出q数组头部的元素
if(i + 1 >= m)
cout << a[q[hh]] << " ";
}
return 0; // 程序结束
}