每日一题——滑动窗口(2)
时间:2021-02-22 12:36:53
收藏:0
阅读:0
滑动窗口(2)
- 绝对差不超过限制的最长连续子数组
给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。
如果不存在满足条件的子数组,则返回 0 。
看到子数组,想到了滑动窗口。
滑动窗口的优点:
- 滑动窗口可以覆盖所有可能性
- 滑动窗口只需要维护两个值:左右端点,且一直前进,时间复杂度为O(N)
本题维护的滑动窗口应该维护“绝对差”小于等于limit的限制,
因此需要维护窗口内的最大值和最小值,并能方便的增加删除特定值的被管理的元素。
std::multiset
看了提示1,推荐使用multiset:
- multiset:与set相同,会对值自动排序;与set不同,可以容纳多个相同值的对象。
- 由于自动排序性质,可以调用
begin()
和end()
来计算最大绝对差 - 使用find()获得所要删除的元素,用erase()轻松删除一个元素;(直接传值给erase会删除所有对应元素)
- 使用insert()传值轻松插入
伪代码:
multiset<int> window(); // default Compare: less
for(int l = 0, r = 0; r < nums.size(); ++r) // sliding window
window.insert(nums[r]); // r progress
while( 不是好窗口 )
l缩进,删除window中的nums[l]
更新maxLen
单调队列
也可以维护最大最小值的候选队列,当最值被剔除出窗口后能有候选值成为最值。
对队列排序,最值的获取就变得很简单,但元素原本的顺序被打乱,窗口滑动时删除元素额外需要了查找操作。
而单调队列可以解决这个问题:
- 单调队列不破坏原有元素顺序
- 后进的元素相较前进的元素生存期长,如果后进的元素的候选资格比前进的元素高,那么前进的元素必然不会再成为最值,可以直接剔除出队列。这就构成了单调队列。
维护单调队列的关键代码:
while(!maxQue.empty() && maxQue.back() < newCandidate)
maxQue.pop_back();
maxQue.push_back(newCandidate);
评论(0)