码迷,mamicode.com
首页 > 其他好文 > 详细

每日一题——滑动窗口(2)

时间:2021-02-22 12:36:53      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:代码   erase   std   c++   push   find   时间   端点   start   

滑动窗口(2)

  1. 绝对差不超过限制的最长连续子数组
    给你一个整数数组 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);

每日一题——滑动窗口(2)

标签:代码   erase   std   c++   push   find   时间   端点   start   

原文地址:https://www.cnblogs.com/laiyk/p/14425775.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!