获取窗口最大值数组 O(n)解法

题目:

一个整型数组num 窗口大小w 从左到右滑动窗口。

窗口滑动过程中每次都会产生一个最大值。【总共产生n - w + 1个窗口】


思路:

常规解法:O(n*w)的解法复杂度太高。
本题解法复杂度:O(n) 大致思想如下:

维护一个双端队列dq 记录遍历的元素下标。 记:num[i]为当前遍历到的元素 dq队尾元素为j。

若 num[i] < num[j] 将i放入队尾   结束。【说明当前元素并没有更新记录的最大值下标】

若 num[i] >= num[j] 将j从队首弹出  继续比较。【说明当前元素的加入会更新最大值 此时需要多步操作更新最大值】

注意:如果队首元素为i-w 那么此时需要将队首从队列弹出,因为此时记录的最大值下标已经不是当前w大小窗口的最大值。


贴代码:

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

void getWindowMax(vector<int> num, int w, vector<int> &maxNum)
{
	if (num.empty() || w < 1 || num.size() < w)
	{
		return;
	}

	// 定义一个双端队列 保存数组元素下标
	deque<int> dq;			// 插入数据在队尾操作  弹出数据在队首操作
	maxNum.resize(num.size() - w + 1, 0);

	int idx = 0;

	// 遍历给定数组num 找出w窗口内的最大值 放入maxNum数组中
	for (int i = 0; i < num.size(); ++i)
	{
		// 队列非空 且当前队尾元素 < 当前数组元素
		// => 弹出队尾
		while(!dq.empty() && num[dq.back()] <= num[i])
		{
			dq.pop_back();
		}
		// 当前队尾元素 < 当前数组元素 => 将当前元素下标放入队尾
		dq.push_back(i);

		// 下标过期 从队首弹出即可
		if (dq.front() == i - w)
		{
			dq.pop_front();
		}

		if (i >= w - 1)
		{
			maxNum[idx++] = num[dq.front()];
		}
	}

}

int main(void)
{
	int a[] = {1, 3, 5, 5, 2, 6, 4};
	int w = 3;
	vector<int> num(a, a + 7);

	vector<int> res;

	getWindowMax(num, w, res);

	if (res.empty() == false)
	{
		vector<int>::iterator it;

		for (it = res.begin(); it != res.end(); ++it)
		{
			cout<<(*it)<<endl;
		}
	}
	else
	{
		cout<<"data error"<<endl;
	}

	return 0;
}
输出结果:

5
5
5
6
6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值