窗口内最大值(或最小值)的更新结构

窗口:数组中的一段数

  1. L与R之间的数就是窗口内的数 
  2. L和R的初始位置为数组的左边,可表示为-1
  3. L和R都只能右移,不可后退;且L不可超过R

双向队列:既可以从头部弹出,也可以从尾部弹出的队列结构

c++表示:deque<int> : double ended queue

相关操作:push_back(), push_front() :从尾部和头部加数据, pop_back(),pop_front()把尾部和头部的数弹出, front(),back()取出头部和尾部的数。

  1. 双向队列中存储数及其数组下标,也可以只存储下标,使用数的时候根据下标去数组查询
  2. 从头到尾数依次递减,不可取等

双向队列中加数策略:R右移,则向双向队列中加数;如果尾部元素比要加入的数小,则弹出尾部的数,一直弹,直到尾部的数大于新加入的数,或者队列为空。

解释:如果新加入的数据,比之前的数大,那么之前的数就不可能是窗口内最大值,可以舍弃掉。

双向队列减数策略: L右移,则需要处理,如果刚被移出窗口的数 是 队列头部的数则把队列头部的数弹出,这就是为什么要保存数组下标的原因。

窗口内最小值类似:双向队列从头到尾依次递增,加数如果尾部数比要加的数大则弹出,减数也是过期就弹出;

例题:

生成窗口最大数组,数组为[4, 3, 5, 4, 3, 3, 6, 7],窗口大小为3,求所有窗口最大值组成的数组:

及窗口[4 , 3, 5];     [3, 5, 4]...等组成的数组。

设数组长度为 n, 窗口大小为 w, 总的窗口数量为n - w + 1

vector<int> maxValuesInWindows(int arr[], int n, int w) {
	vector<int> res;
	deque<int> qmax;//双向队列
	for (int i = 0; i < n; i++){
		while (!qmax.empty() && arr[qmax.back()] < arr[i]) {//加数
			qmax.pop_back();
		}
		qmax.push_back(i);
		if (qmax.front() == i - w) {//减数
			qmax.pop_front();
		}
		if (i >= w - 1) {
			res.push_back(qmax.front());
		}
	}
	return res;
}

猜你喜欢

转载自blog.csdn.net/qianji_little_boy/article/details/83591712