滑动窗口解决的问题:
【题目】
有一个整型数组arr和一个大小为w的窗口,从数组的最左边滑到最右边,且滑动过程中窗口大小可伸缩。
例如,数组为 [4, 3, 5, 4, 3, 3, 6, 7], 窗口滑动过程为:
[ 4 3 5 ] 4 3 3 6 7
4 [ 3 5 ] 4 3 3 6 7
4 [ 3 5 4 ] 3 3 6 7
4 [ 3 5 4 3 ] 3 6 7
4 3 [ 5 4 3 ] 3 6 7
4 3 5 [ 4 3 ] 3 6 7
4 3 5 [ 4 3 3 ] 6 7
4 3 5 [ 4 3 3 6 ] 7
窗口中最大值依次为5, 5, 5, 5, 5, 4, 4, 6
设计一种数据结构,随时获得窗口中的最大值。
使用双端队列。
R右移:在队列尾加入元素,如果当前尾元素小于等于要加入的元素,弹出,直到队列空或当前尾元素大于要加入的元素。
L左移:检查队列头元素是否为L移动前所在元素,是则去掉头元素,否则return。
这样,双端队列从头到尾是当前窗口内数组从左到右依次过期,依次会有哪些数字成为最大值。
因此,R右移时:
如果加入的数字大于队尾元素,则:
1)加入的数字比队尾元素大
2)加入的数字比对尾元素晚过期
因此对尾元素没有存在的必要了,故弹出。
如果加入的数字等于队尾元素,则:
1)加入的数字与队尾元素等大
2)加入的数字比对尾元素晚过期
因此对尾元素没有存在的必要了,故弹出。
class Window{
public:
int L;
int R;
vector<int> arr;
deque<int> q;
Window(vector<int>& nums){
this -> L = -1;
this -> R = -1;
arr.assign(nums.begin(), nums.end());
}
void addNumFromRight(){
if(R == arr.size() - 1){
return;
}
R = R + 1;
while(!q.empty() && arr[q.back()] <= arr[R]){
q.pop_back();
}
q.push_back(R);
}
void removeNumFromLeft(){
if(L >= R){
return;
}
L++;
if(q.front() == L){
q.pop_front();
}
}
int getMax(){
if(!q.empty()){
return arr[q.front()];
}
else{
return INT_MIN;
}
}
};