【问题标题】:Can min/max of moving window achieve in O(N)?移动窗口的最小值/最大值可以在 O(N) 中实现吗?
【发布时间】:2012-08-24 18:52:26
【问题描述】:

我有输入数组 A

 A[0], A[1], ... , A[N-1]

我想要函数 Max(T,A),它返回 B 表示 A 上大小为 T 的前一个移动窗口的最大值,其中

 B[i+T] = Max(A[i], A[i+T])

通过使用最大堆来跟踪当前移动窗口 A[i] 到 A[i+T] 的最大值,该算法产生 O(N log(T)) 最坏情况。

我想知道有没有更好的算法?也许是 O(N) 算法

【问题讨论】:

  • 如果A 是固定的,而T 变化,你可以做一个O(N*log(N)) 准备,然后对于每个T,你可以在O(N) 时间内得到B
  • @Topro 听起来不错!你能把准备步骤放在答案上吗?谢谢!

标签: arrays algorithm heap max min


【解决方案1】:

它被称为RMQ(范围最小查询)。实际上我曾经写过一篇关于那个的文章(使用 c++ 代码)。见http://attiix.com/2011/08/22/4-ways-to-solve-%C2%B11-rmq/

或者您可能更喜欢维基百科,Range Minimum Query

准备好之后,可以得到O(1)中任意给定范围的最大数量

【讨论】:

  • 所以它需要额外的 O(N log(N)) 空间?我花了很长时间才理解准备步骤的全部内容,这基本上是动态编程构造:) 但是,是的,我确实需要改变很多 T。这种方法比其他方法有优势吗?
  • @dondonchi 为您返回任何查询的最小值(l,r),无需修复 T。
【解决方案2】:

O(N) 可以使用 Deque 数据结构。它包含对(值;索引)。

at every step:

  if (!Deque.Empty) and (Deque.Head.Index <= CurrentIndex - T) then 
     Deque.ExtractHead;
  //Head is too old, it is leaving the window

  while (!Deque.Empty) and (Deque.Tail.Value > CurrentValue) do
     Deque.ExtractTail;
  //remove elements that have no chance to become minimum in the window

  Deque.AddTail(CurrentValue, CurrentIndex); 
  CurrentMin = Deque.Head.Value
  //Head value is minimum in the current window

【讨论】:

  • bravo,适用于更一般的情况
  • 不应该顶部的“if”是一个“while”,以防我们可以从头部修剪多个值?例如,如果头部有两个具有相似索引值的元素,并且新的索引值足够远,这意味着这两个旧元素现在已过期。
  • @John Zwinck 不,索引是唯一的,它是元素的“年龄”。在第二个条件下检查'='就足够了,而不是'
  • @Cris Luengo 不需要排序。最小项目位于队列头部,直到更好的项目替换它,删除所有项目(第二个操作员)或者它变得太旧(第一个操作员)
【解决方案3】:

图像处理中有一个子领域称为数学形态学。您正在实施的操作是该领域的一个核心概念,称为dilation。显然,这个操作已经被广泛研究,我们知道如何非常有效地实现它。

这个问题最有效的算法是在 1992 年和 1993 年由 van Herk、Gil 和 Werman 独立提出的。该算法每个样本需要进行 3 次比较,与 T 的大小无关。

几年后,Gil 和 Kimmel 进一步改进了算法,使每个样本只需进行 2.5 次比较。尽管该方法增加的复杂性可能会抵消较少的比较(我发现更复杂的代码运行得更慢)。我从未实现过这个变体。

所谓的 HGW 算法需要两个与输入大小相同的中间缓冲区。对于非常大的输入(数十亿个样本),您可以将数据分成块并逐块处理。

在排序中,您向前遍历数据,计算大小为T 的块的累积最大值。你倒着走也一样。这些中的每一个都需要对每个样本进行一次比较。最后,结果是这两个临时数组中每一个中一个值的最大值。对于数据局部性,您可以同时对输入进行两次传递。

我猜你甚至可以做一个运行版本,其中临时数组的长度为2*T,但实现起来会更复杂。

  • van Herk,“矩形和八边形核上局部最小和最大滤波器的快速算法”,模式识别快报 13(7):517-521, 1992 (doi)

    李>
  • Gil, Werman,“计算二维最小值、中值和最大值滤波器”,IEEE Transactions on Pattern Analysis and Machine Intelligence 15(5):504-507 , 1993 (doi)

  • Gil, Kimmel,“高效膨胀、腐蚀、打开和关闭算法”,IEEE Transactions on Pattern Analysis and Machine Intelligence 24(12):1606-1617, 2002 (doi)

(注:交叉发布自this related question on Code Review。)

【讨论】:

    猜你喜欢
    • 2019-12-04
    • 2020-03-29
    • 2012-05-30
    • 2020-06-21
    • 2012-01-19
    • 2017-04-03
    • 1970-01-01
    • 2019-07-09
    相关资源
    最近更新 更多