恒定时间内任何子阵列的最大值和最小值

Maximum & Minimum of any subarray in constant time

提问人:user8524786 提问时间:8/19/2022 最后编辑:Matt Timmermansuser8524786 更新时间:8/20/2022 访问量:592

问:

我是一名计算机科学工程专业的学生,我在许多任务中都遇到了这个问题。

我得到了一个带有值的大小数组,然后询问了一些查询

在每个查询中,我都会得到两个索引,其中.

我相信,如果进行了一些预处理,有一种方法可以回答这个问题。

我必须在.

这个问题我已经很多天了,但我根本无法理解。

数组 算法 数据结构 与语言无关 动态规划

评论

0赞 PaulMcKenzie 8/19/2022
这不是一个 C++ 问题。
1赞 PaulMcKenzie 8/19/2022
然后问了一些问题——“查询”这个词对你来说可能很有意义,但我不知道你说的“查询”是什么意思。这听起来很像那些“竞争性编程”问题之一。
1赞 Peter de Rivaz 8/19/2022
这看起来像一个 RMQ 问题(范围最小查询)。有一个很好的教程 topcoder.com/thrive/articles/...
2赞 fabian 8/19/2022
当然,如果进行了适当的预处理,则可以在 中解决。只需使用任意算法来确定所有可能组合的结果,并将结果存储在数据结构证明查找中。完成此预处理后,程序将在 中运行。当然,预处理会非常慢。一个可能更合理的方法是构建一个二叉树,并将最大值存储在每个节点的每个子数组中,从而允许使用预处理时间和额外的内存进行查找......O(1)lrO(1)O(1)O(log(N))O(N)O(N)
2赞 Jim Mischel 8/19/2022
题目写着“在恒定时间内”,但题文上写着“我必须在 O(n) 中完成”。它是什么?你真的需要澄清你的问题。

答:

4赞 Matt Timmermans 8/19/2022 #1

此问题称为“范围最小查询”。它经过了充分的研究,如果你在谷歌上搜索一下,你最终会得到众所周知的、非常聪明的、相当复杂的数据结构,它满足了你的要求,需要 O(N) 空间和预处理时间。

在这里,我将提供一个更简单的解决方案,当您的数组包含少于 264 个项目时,该解决方案在实践中表现更好......即,总是。

我只谈谈找到最小值,但当然找到最大值需要类似的结构。

与众所周知的数据结构一样,它使用这个作为组件:

简单的 O(N log N) 空间解决方案

给定一个包含 N 个项目的数组 A,设 M = ceil(log2 N)。

制作一个大小为 NxM 的矩阵 W,对于每个 (i,j),其中 0 < i < N 和 1 < j < M,将 W[i][j] 分配给从 A[i] 开始的 2个 j 元素中最小值的索引,在数组的末尾停止。

所以现在,对于每个大小为 2j 的窗口,我们有其最小值的索引。由于每个子数组最多被 2 个重叠窗口覆盖,因此我们可以通过检查这 2 个窗口并选择其 2 个最小值中的较低值来轻松找到任何子数组中的最小值。

初始化此数据结构可以在每个项目的恒定时间内完成。如果先执行较小的窗口大小,则可以通过合并 2 个较小窗口的结果来找到每个窗口最小值。

此解决方案需要为每个数组项存储日志 N 索引。

O(N)空间解决方案

为了使解决方案适合 O(N) 空间,我们需要在 2 个级别使用上述数据结构:

  1. 将输入分成 64 个元素的块。选择每个块中最小的项目作为其代表。为代表数组实现 O(N log N) 解决方案。鉴于 N < 2 64,这要求每个块存储少于64 个索引,即每个项目最多存储一个索引 -- O(N)
  2. 为每个块中的 64 个项目分别实现 O(N log N) 解决方案。这需要每件商品最多存储 6 个索引,尺寸为 64、32、16、8、4、2。但是每个索引只需要 6 位或更少。窗口大小 2 的索引仅占用 1 位。因此,这 6 个索引可以打包到每个项目一个 32 位字中——再次 O(N)。(实现说明:仍然在阵列端切断窗口,而不是块端)

现在,我们每个项目只花费了 8 或 12 个字节(取决于数组索引是 32 位还是 64 位),我们可以轻松地在恒定时间内回答任何范围最小查询:

  • 最多检查 2 个重叠的块表示窗口,以查找查询涵盖的所有完整块中的最小值;
  • 最多检查 2 个部分块窗口以覆盖查询的其余部分;
  • 返回找到的最小值。