【问题标题】:how to build a max heap on a given array and given indices of the array?如何在给定数组和给定数组索引上构建最大堆?
【发布时间】:2013-02-07 02:38:48
【问题描述】:

我有以下问题:

给定一个整数数组 A,并给定 t 个不重叠部分 [L1,R1],[L2,R2]...[Lt,Rt]

使得每个部分都是数组(A)处的开始索引(Li)和结束索引(Ri),

找到一个数据结构,以 O(t + klogk) 复杂度返回这些部分中的前 k 个元素(索引在这些部分,元素在数组 A)。

非常感谢帮助者, 阿维海。

【问题讨论】:

    标签: data-structures heap


    【解决方案1】:

    问题的措辞有点模棱两可:在复杂性O(t+klogk) 中,哪些算作要完成的操作的一部分?

    我在回答这个问题时看到了 3 个选项。对于前两个,我认为这是解释原始问题的错误方式,我提供了答案。对于第三个也是最后一个选项,我没有解决方案。我仍然认为有必要把问题说清楚,并将我的答案添加到前两个中。此外,如果不是不可能的话,在评论中添加对此事的长时间讨论也会令人困惑。

    以下是我看到的用于回答我开始的问题的选项:

    选项 1 - 不包括数据结构构建(使用部分)

    从原始问题的当前措辞看来,该问题要求可以使用数组A[L1,R1],[L2,R2],...,[Lt,Rt] 部分预先构建的数据结构,并且考虑复杂性要求的唯一操作是对数据结构进行的操作以提取k 的最高值。

    这没有多大意义,因为不清楚为什么在这种情况下将t 置于复杂性中?从 this answer,您在评论中链接到 Juan 的答案,您可以看到,通过仅使用相关元素预先构建堆,您可以获得 O(klogk) 以从数据结构中获取 k 最高值元素(一旦存在)。

    选项 2 - 包括所有操作

    如果我们阅读它,就好像问题要求构建数据结构作为考虑复杂性要求的操作的一部分(我们只得到数组和索引列表[L1,R1,L2,R2,...,Lt,Rt] 并且必须使用它)那么复杂性要求不可能实现。如果你想建立一个数据结构,你至少需要检查所有需要插入数据结构的元素,如果你不想建立一个数据结构并且你打算使用数组作为它那么你将不得不检查你需要找到最大值的所有元素。无论哪种方式,如果您得到t=1L1=1, R1=n,其中n 是数组A 中的元素数,您将不得不检查A 中的所有元素(您对A 没有任何假设'元素'顺序)。这意味着您至少需要O(n) 并且要求是O(t+klogk)。为了更清楚地说明这些是完全不相关的数量 - 您可以考虑 k=1 的情况,这意味着只找到最高元素,而 A 可以是任意长度(比如说 10,000)。

    选项 3 - 仅使用数组豁免构建数据结构

    这让我猜到了问题背后的原始含义:事先从给定数组A 构建一个数据结构(其构建将不包括在复杂性要求中),以便稍后您给定部分的索引[L1,R1],[L2,R2],...[Lt,Rt] 和一个整数k,您之前构建的数据结构将允许您在原始数组@987654345 中由新给定索引(L1,R1,L2,R2,...,Lt,Rt)定义的部分中获得k 最高元素@复杂O(t+klogk)。 不幸的是,我还没有想出解决这个问题的方法——或者证明不存在这样的解决方案,但至少现在这个问题是有意义的。

    我很想知道哪个选项是问题的初衷,如果我想出选项 3 的解决方案,我会相应地编辑这个答案。

    【讨论】:

      【解决方案2】:

      我会构建一个间接表 T,它将 [0..t] 映射到由部分映射的索引。

      然后我会使用这个间接表运行 heapify 算法。每次算法访问 A[i] 时,都会被 A[T[i]] 替换。

      间接表构造和堆化都是O(t)。获取前 k 个元素将花费 O(t log n)。

      编辑: Wikipedia explains 在其文章中如何在 O(t) 中构建堆。

      基本上是一系列的冒泡操作:

      for i from floor(A.size()/2) to 0:
          bubble_down(A, i)
      

      文章中有证明为什么这是 O(t)。

      【讨论】:

      • 首先,谢谢。其次,我在这里看到了一个解决“top-k 元素”问题的方法,即按 O(klogk) 的顺序工作的堆(非常好的解决方案),问题是如何按 O(t) 的顺序构建这个堆?您的解决方案是 O(tlogn),我担心它无法满足,我附上了解决方案的链接(请参阅 Victor Nicollet 的答案)。 link
      • @JuanLopes 您添加了在 O(n) 中构建堆的详细信息和说明,其中 n 是已构建堆中的元素数。这不是 O(t)。在上面的问题中,t 是部分的数量。
      • @et_l 如果我用 t 个元素堆积一个数组,那就是 O(t),不是吗?我可能遗漏了一些东西,我从这个答案中记得很少。
      • @JuanLopes 是的,当然是。但是问题中没有包含t 元素的数组。如果我理解正确的话,有t 对定义原始数组A 中任意长度部分的索引。我将我的想法放在答案中,因为评论太长且太复杂,但我认为问题的措辞是错误的。简短的故事:我认为它的意思是要求我们预先仅使用数组A 构建一个结构,然后给定部分(L1,R1,...Lt,Rt)和一个整数k 得到k 复杂度最高的元素O(t+klogk).
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-13
      • 2016-01-27
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      相关资源
      最近更新 更多