合并两个二进制最大堆,其中一个堆中的所有元素都大于另一个堆中的所有元素?

时间:2017-10-22 18:18:15

标签: algorithm data-structures heap

我参加了这个编程面试问题,我不确定我的答案是否正确。我无法找到这个问题的正确答案。这是问题,

  

设H1和H2为n1和n2个元素的两个(二进制)max-heaps   分别。如果H1中的每个元素都大于中的每个元素   H2,设计一种算法,将这两个堆合并为一个(二进制)   O(n2)时间内的最大堆(假设H1和H2都足够大)   持有n1 + n2个元素)

所以,我认为由于H1中的每个元素都大于H2中的每个元素,因此我们可以将合并的最大堆存储在H1中。因此,我们所要做的就是从H2获取第一个元素,在H2的数组中的第0位,然后将该元素插入H1,附加到H1数组的末尾,使其成为H1中的叶子。我们可以继续为H2中的每个元素做到这一点。我想,一旦我们开始将H2中的元素作为子元素添加到H2的元素中,那么我们将不得不开始检查该子元素是否小于父元素,如果不是,则我们交换它们。我假设因为添加一个元素而不调用heapify,并在必要时交换会给我们一个复杂的O(n2)。

那么,我的解决方案是否准确?如果没有任何帮助将不胜感激。 请告诉我,如果我的解决方案的任何部分不清楚,我可以澄清一下。

1 个答案:

答案 0 :(得分:2)

一般情况下,只能将H2附加到H1上,因为正如评论中指出的那样,这样做会产生无效的堆。这种情况并不是特别罕见。

例如,想象两个最大堆:

h1 = [100]
h2 = [6,3,5,1,2,4]

    h1        h2

   100        6
            3   5
           1 2 4

如果你只是将h2追加到h1,你会得到:

    100
  6    3
 5 1  2 4

这显然是无效的,因为4是3的孩子。

如果h1 = [100,98],可能会发生同样的事情:

       100
    99     6
   3  5  1   2
 4

你需要做的是将h2追加到h1,然后运行缩写的 build-heap ,重新排列h2中的项目以反映它们在堆中的新位置。您已经知道从h2添加的所有项目都小于h1中的最小项目,因此您不必触及h1中的任何项目。

这与标准 build-heap 之间的唯一区别是起始位置和结束位置。基本上,你从h2的中间开始,然后向后工作到h2的开头。

h1_length = h1.length
h2_length = h2.length
h1.array.append(h2.array)  // copies items from h2 to h1
// rearrange h2 items
start = h1_length + (h2_length/2)
for (item = start; item > h1_length; --item)
{
    i = item
    // This assumes that the root of the heap is at 0.
    // If the root is at 1, then the left child is at i*2
    while (i*2+1 < h1.length)
    {
        // get the largest child of this item
        leftChildIndex = i*2+1
        rightChildIndex = leftChildIndex + 1
        largestChildIndex = leftChildIndex
        if (rightChildIndex < h1.length &&
            h1.array[rightChildIndex] > h1.array[leftChildIndex)
        {
            largestChildIndex = rightChildIndex
        }
        // if the item is greater than or equal to its largest child,
        // then the item is where it belongs.
        if (h1.array[i] >= h1.array[largestChildIndex])
        {
            break;
        }
        // swap the item with its child, and check again
        swap(h1.array[i], h1.array[largestChildIndex])
        i = largestChildIndex
    }
}

build-heap 算法被证明是O(n),其中n是您正在构建的堆中的项目数。由于您只使用h2.length项,因此需要O(h2.length)时间。