显然我们是需要同时维护当前的最大值和最小值,这就需要两个单调队列dq_down(递减排列)一个维护最大值,dq_up(递增排列)一个维护最小值,同样这个是使用我们第二个模板 [left, i].
只有当left等于某一个dq.front()的时候,才把它pop_front().这就使得对应相同的元素,我们只需要保留一个就行,也就是说在队尾遇见了相同的元素,我们可以直接加入,也可以删除相同的再加入.
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
deque<int> dq_up;
deque<int> dq_down;
int left=0,ans=0;
for(int i=0;i<nums.size();i++){
while(!dq_up.empty() && nums[i]<=nums[dq_up.back()]){
dq_up.pop_back();
}
dq_up.push_back(i);
while(!dq_down.empty() && nums[i]>=nums[dq_down.back()]){
dq_down.pop_back();
}
dq_down.push_back(i);
while(!dq_up.empty() && !dq_down.empty() && nums[dq_down.front()]-nums[dq_up.front()]>limit){
if(left==dq_up.front()){
dq_up.pop_front();
}
if(left==dq_down.front()){
dq_down.pop_front();
}
left++;
}
ans=max(ans,i-left+1);
}
return ans;
}
// s.erase(s.find(nums[left++])) 改成: s.erase(nums[left++])
//前者是使用迭代器删除,是只删除一个元素
//后者是使用重载的value删除,删除所有等于value的元素
};
开始的时候我一直担心pop_back这里会影响left, 也就是说为了维护单调性会删除错误的元素,但是后来我发现其实不会,因为它删除的元素都是在left边界之前的, 不会影响left
而且其实最后一个while可以写成if, 因为每次最多只需要删除一个元素, right只会+1 而之前的ans已经保存了上一次 r-l+1 的正确的数值