【问题标题】:Algorithm for walking over non-overlapping intervals遍历非重叠区间的算法
【发布时间】:2017-04-08 00:08:37
【问题描述】:

我有一个排序的非重叠间隔列表(从零开始,半开),例如

{[0, 5), [10, 20), [35, 40)}

假设我在其中一个间隔中有一个点(例如,在这种情况下为 3)和一个步长值为 +10(即向右移动 10 个位置)。有没有一种算法可以在 O(1) 时间内计算出我的最终位置? (编辑:也许我应该说,比 O(n) 更好)

区间未覆盖的数字被视为不存在的位置,因此在上述区间上使用步骤 +10 的位置 3 将导致最终位置为 19+1 将我的位置移动到 4,然后剩余的+9 从位置10 开始直到位置19)。另一个例子是,如果我们将位置 15 作为起点,步长值为 -10,那么最终位置将是 0

为简单起见,我们还可以假设最终位置总是以某个区间结束。然而,我们可能知道也可能不知道应该从哪个时间间隔开始计数。

我当然可以在 O(n) 时间内迭代间隔列表(n = 间隔数)。但我觉得应该有更好的方法来解决这个问题。

附:这个问题有名字吗?这感觉它应该有一个合适的名称,但我不确定它是什么。

【问题讨论】:

  • 您不能只使用预处理步骤将所有值放入一个数组中,然后在 O(1) 中获取它们吗?如果您多次执行此操作(至少 Omega(n) 次),则平均成本为 O(1)...
  • 您可以通过将区间排列成二叉树来轻松获得对数时间(非叶节点应同时公开其子树的最小覆盖区间和宽度的实际总和)。不过,我不确定如何达到恒定时间。
  • @Useless 您介意将您的评论转换为更详细的答案吗?我对具体细节感兴趣,显然这是一个正确的解决方案。

标签: algorithm intervals


【解决方案1】:

您可以通过将区间排列成二叉树来轻松获得对数时间(非叶节点应同时公开其子树的最小覆盖区间和宽度的实际总和)

所以,稍微改变一下你原来的间隔,

{[0, 5), [15, 20), [25,30), [35, 40)}

将被表示为像一棵树

               {cover:[0,40), size:20}
              /                       \
{cover:[0,20), size:10}  {cover:[25,40), size:10}
      /           \              /           \
{[0,5), 5} {[15,20), 5}  {[25,30), 5} {[35,40), 5}

其中cover是覆盖子树的最小区间,size是不包括间隙的区间宽度。

因此,为了处理您的 3 + 10 案例,我们会执行以下操作:

  1. 正则二叉树搜索找到包含3的区间(对数时间)
  2. 我们正在向右移动(正步骤),这个区间覆盖了那个方向的5-3=22<10,所以我们还没有完成:调整剩余距离 (10-2=8) 并在树中向右移动。

    当前节点是我们父节点的左孩子,所以这意味着接下来看右孩子

  3. 此时间间隔涵盖5<8,所以我们还没有完成。调整剩余距离 (8-5=3) 并再次在树中向右移动。

    当前节点是我们父母的右孩子,所以这意味着上升一个级别,在这种情况下是我们祖父母的右孩子

  4. 这个区间覆盖10>3,所以我们的终点就在这里。然而,这不是一片叶子,所以我们需要再往下走,从左孩子开始。请注意,父/子范围重叠,因此我们在此步骤中不会消耗任何剩余距离。

  5. 这个区间覆盖了5>3,所以我们终于找到了正确的叶子区间。我们的端点是 25+3 = 28。

请注意,虽然遍历权看起来是线性的,但如果有中间子树,我们可以跳过。不太清楚,但仍应为对数。

【讨论】:

  • 感谢您提供详细信息。
  • 啊哈,存储区间跨度确实是个好主意。我想我对现在可以做什么有了更好的把握。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
  • 1970-01-01
  • 2011-11-08
相关资源
最近更新 更多