使用数组在O(log n)时间内搜索和删除

时间:2015-11-11 11:32:18

标签: data-structures amortized-analysis

假设我们最初得到一组n个数字。我们需要构建一个支持Search(),Predecessor()和Deletion()查询的数据结构。

搜索和前置任务应该采用最坏情况O(日志处理n)时间。删除应采用摊销的O(log n)时间。允许的预先时间是O(n)。我们最初有O(n)空间。但我希望在任何阶段,如果它们是结构中的m个数字,则使用的空间应为O(m)

这个问题可以通过RBT轻松解决,但我想要一个仅使用数组的数据结构。我不想使用数组实现RBT,数据结构不应该使用任何来自树的算法。谁能想到一个这样的数据结构?

1 个答案:

答案 0 :(得分:0)

我可以建议某种树结构,这比RBT容易。为了简化描述,让其中的元素数量为2^k

第一级只是数字。 第二级a级有2^(k-1)个数字,就像在二叉树中一样。 下一级a有2^(k-2)个数字,依此类推,直到我们只有一个数字。 所以我们有一个带有2^(k+1)个节点的二叉树,父节点将包含最多的子节点值。要构建此树,我们将O(N)时间。树将消费者O(n)空间,第一级消费者n,第二个n/2,第三个n/4 ...等等,因此总空间将为n + n/2 + n/4 + ... = 2n = O(n)。例如。对于数字1,2,4,6,8,9,12,14,我们将有以下树:

 1  2  4  7  8  9 12  14 

   2    7     9     14 

      7          14

            14

要删除元素,我们需要使用二进制搜索找到它,并在列表中将它们标记为null。更新树,如果两个子NULL都将NULL放到节点上。它将采取k操作(树高)或O(log(N))。 例如。我们删除了12.

 1  2  4  7  8  9 NULL(12)  14 

   2    7     9     14 

      7          14

            14

现在删除7。

 1  2  4  NUll(7)  8  9 NULL(12)  14 

   2    4            9     14 

      4                 14

            14

现在我们应该在O(log(N))中搜索或前导。通过二进制搜索在第一级找到我们的元素或它的前身。如果它不是NULL,我们得到答案。如果NULL升级,我们在这里有三个变体:

  1. 节点具有NULL值,转到上一级
  2. 节点的左子节点具有非NULL值。它小于请求的数量(由于树结构),它就是答案。
  3. 节点的值大于当时请求的数字,请更高。