E - 魔法猫咪 & 质量序列

本文介绍了两种方法解决C++中的滑动窗口问题:暴力遍历与使用单调队列优化。暴力解法通过外层循环遍历数组,而单调队列法利用队列数据结构在O(n)时间内找到每个窗口内的最小值。
摘要由CSDN通过智能技术生成

暴力做法:

#include <iostream>

using namespace std;

int main()
{
    int n, l;
    int s[1000];
    cin >> n >> l;

    for (int i = 0; i < n; i++)
        cin >> s[i];

    for (int i = 0; i <= n - l; i++)
    {//外层循环遍历每一个起始点 
        int k = s[0];
        for (int j = 0; j < l; j++)
        {
            if (s[j] < k)
                k = s[j];
        }
        cout << k << endl;
    }

    return 0;
}

来自学长的代码:(注释仅代表本人的见解) 

#include <bits/stdc++.h> // 包含通用的C++标准库头文件
using namespace std;

int n, m; // n表示数组长度,m表示滑动窗口大小
int a[100010]; // 存储输入的整数数组
int q[100010], hea = 1, tai = 0; // 单调队列,hea表示队列头部位置,tai表示队列尾部位置

int main() {
    cin >> n >> m; // 从标准输入读取n和m

    // 读取数组a的元素
    for (int i = 1; i <= n; i++) {
        cin >> a[i]; // 读取第i个元素的值

        // 维护单调递减队列
        while (1) {
            // 如果当前元素小于队尾元素且队列非空,则弹出队尾元素,直到队列为空或者当前元素大于等于队尾元素
            if (a[i] < a[q[tai]] && hea <= tai)
                tai--;
            else {
                // 否则将当前元素的下标i加入队尾
                q[++tai] = i;
                break;
            }
        }

        // 检查队头元素是否已超出窗口范围,若是,则弹出队头元素
        if (i - q[hea] + 1 > m)
            hea++;

        // 如果当前下标i大于等于窗口大小m,则说明已经可以输出窗口内的最小值了
        if (i >= m)
            cout << a[q[hea]] << endl; // 输出窗口内的最小值
    }

    return 0;
}

deque

#include <iostream>
#include <deque>
#include <vector>
using namespace std;
int main()
{
	int n, m;
	cin >> n >> m;
	vector<int>arr(n + 1);		//用来存数据
	deque<int>q;		//双端队列,用来存m范围内最小数的下标
	for (int i = 1; i <= n; i++)
	{
		cin >> arr[i];
		while (1)
		{
			if (q.size() && arr[i] < arr[q.back()])q.pop_back();//只有当双端队列里面有数时才能进行比较,如果小于队尾元素,则弹出队尾。
			else {
				q.push_back(i);		//如果队列里面没数了,或者i>队尾元素则直接把该i下标放入队列中
				break;
			}
		}
		if (i - q.front() + 1 > m)q.pop_front();		//当队头元素不属于m区间范围了,则弹出队头元素,换下一个队头
		if (i >= m)cout << arr[q.front()] << endl;		//当进行m次后输出队头元素
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值