假设我们最初得到一组n个数字。我们需要构建一个支持Search(),Predecessor()和Deletion()查询的数据结构。
搜索和前置任务应该采用最坏情况O(日志处理n)时间。删除应采用摊销的O(log n)时间。允许的预先时间是O(n)。我们最初有O(n)空间。但我希望在任何阶段,如果它们是结构中的m个数字,则使用的空间应为O(m)
这个问题可以通过RBT轻松解决,但我想要一个仅使用数组的数据结构。我不想使用数组实现RBT,数据结构不应该使用任何来自树的算法。谁能想到一个这样的数据结构?
答案 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升级,我们在这里有三个变体: