zoukankan      html  css  js  c++  java
  • AcWing 154. 滑动窗口 单调队列

    地址 https://www.acwing.com/problem/content/description/156/

    输入格式

    输入包含两行。

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

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

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

    输出格式

    输出包含两个。

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

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

    输入样例:
    8 3
    1 3 -1 -3 5 3 6 7
    输出样例:
    -1 -3 -3 -3 3 3
    3 3 5 5 6 7

    算法1
    单调队列
    求最大值和最小值的过程其实是一样的 就是求极值的过程
    以求最小值为例
    我们使用一个队列来进行记录 处于滑动窗口的m个数字
    以插入的数据的角度来看
    如果插入的数据比之前的m-1个数字都小 那么它就将清空之前的m-1个数字成为队首
    如果插入的数据比之前m-1个数字中的某一个数字较大 那么它在该数字退出队列后 还是有可能成为最小数值的,也需要保留该插入数字,只不过插入的数字不是队首(以后有可能成为队首)

    这个队里有三个性质
    1 队首是最小数(以求最小值为例)
    2 队列中队首和队尾数字的索引差值最大为m,也就是控制数值在滑动窗口范围内
    3 队列中前部的数字如果比后面的数字大,那么在m个的滑动窗口中,它是不可能成为最小值(队首)的,需要排除出队列

    这样就保证了队列的单调性
    该队列记录的是数字的索引 方便控制当前记录的数值范围 而不是数字的值 这个需要注意

    时间复杂度
    参考文献

    代码

     1 #include <iostream>
     2 #include <deque>
     3 #include <vector>
     4 
     5 using namespace std;
     6 
     7 /*
     8 输入样例:
     9 8 3
    10 1 3 -1 -3 5 3 6 7
    11 输出样例:
    12 -1 -3 -3 -3 3 3
    13 3 3 5 5 6 7
    14 */
    15 
    16 
    17 int n, m;
    18 
    19 int arr[1000010];
    20 deque<int> min_val, max_val;
    21 vector<int> s_min, s_max;
    22 
    23 int main()
    24 {
    25     cin >> n >> m;
    26 
    27     for (int i = 0; i < n; i++) {
    28         cin >> arr[i];
    29     }
    30 
    31 
    32     for (int i = 0; i < n; i++) {
    33         //
    34         while (!min_val.empty() && ( i - min_val.front()) >= m)
    35             min_val.pop_front();
    36         while (!max_val.empty() && (i - max_val.front()) >= m)
    37             max_val.pop_front();
    38 
    39         while (!min_val.empty() && arr[min_val.back()] >= arr[i])
    40             min_val.pop_back();
    41 
    42         while (!max_val.empty() && arr[max_val.back()] <= arr[i])
    43             max_val.pop_back();
    44 
    45         min_val.push_back(i);
    46         max_val.push_back(i);
    47 
    48         s_min.push_back(min_val.front());
    49         s_max.push_back(max_val.front());
    50     }
    51 
    52     for (int i = m - 1; i < n; i++)
    53         cout << arr[s_min[i]] << " ";
    54     cout << endl;
    55     for (int i = m - 1; i < n; i++)
    56         cout << arr[s_max[i]] << " ";
    57 
    58 
    59     return 0;
    60 }
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    equals 和 == 的区别
    jenkins
    状态码
    对控制反转和依赖注入的突然顿悟
    分布式事务与Seate框架
    synchronized原理
    VS 添加 Sqlserver
    C# 生成二维码
    jQuery /Date(0000000000000)/日期转换
    什么是Java的序列化,在哪些程序中见过Java序列化?
  • 原文地址:https://www.cnblogs.com/itdef/p/11526980.html
Copyright © 2011-2022 走看看