【NC51001】Sliding Window

题目

Sliding Window

滑动窗口

思路

这是一道滑动窗口的经典题,题目是英文的,但是也很好懂,这里直接将问题抽象出来:

给你一个长度为 n n n 的数组和一个长度为 k k k 的滑动窗口,让你得出窗口从左滑到右的每一步窗口中的最大值和最小值,并打印出来。

题目很直观,但是有一点小麻烦,如果按朴素的方法求解窗口内的最大最小值的话,那复杂度就会很高(我没有测试过按朴素方法能不能过),有可能过不了。所以我们得找一个比较快的方法来得出窗口内的最大最小值,由于窗口是滑动的,则每移动一个位置,就有一个元素被丢弃,一个元素被新加入,所以这道题的核心就是动态维护最大值和最小值。

使用排序树(比如红黑树)就可以很好的解决这个问题,然而红黑树太复杂,不必手搓,使用 S T L STL STL 封装的 s e t set set 即可。并且,窗口内的元素有可能有重复的,所以我们要使用 m u l t i s e t multiset multiset 来存储窗口内的元素,每当窗口移动时, m u l t i s e t multiset multiset 中就相应地增加和减少元素即可。具体见代码。

代码

#include <iostream>
#include <set>
#include <vector>
using namespace std;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n = 0, k = 0, i = 0;
    cin >> n >> k;
    vector<int> a(n), mm, mn;
    for (i = 0; i < n; i++) {
        cin >> a[i];
    }
    multiset<int> st;
    for (i = 0; i < n; i++) {
        if (i >= k) {
            mn.emplace_back(*st.begin());
            mm.emplace_back(*prev(st.end()));
            // 注意这里erase不能使用值传递版的重载函数
            // 而必须使用迭代器版的重载函数,想想为什么
            st.erase(st.find(a[i - k]));
        }
        st.emplace(a[i]);
    }
    mn.emplace_back(*st.begin());
    mm.emplace_back(*prev(st.end()));
    for (auto&& c : mn) {
        cout << c << " ";
    }
    cout << endl;
    for (auto&& c : mm) {
        cout << c << " ";
    }
    cout << endl;
    return 0;
}
  • 29
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木又可可

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值