好吧,你已经接近了 - 但仍然缺少一些东西,因为从排序数组中插入/删除是O(n)
(因为插入元素的概率为 1/2 位于数组的前半部分,你将不得不向右移动以下所有元素,其中至少有 n/2,因此此操作的总复杂度O(n)
平均为 + 最坏情况)
但是,如果您将排序的 DS 切换到跳过列表/平衡 BST - 您将获得O(logn)
插入/删除和O(1)
最小/最大/中值/大小(带缓存)
编辑:
您无法O(logN)
在插入时变得更好(除非您减少peekMedian()
to Omega(logN)
),因为这将使您能够更好地排序O(NlogN)
:
首先,请注意,对于您插入的每个“高”元素,中位数向右移动一个元素(在这里,高意味着 >= 当前最大值)。
所以,通过迭代地做:
while peekMedian() != MAX:
peekMedian()
insert(MAX)
insert(MAX)
您可以找到排序数组的“较高”一半。
使用相同的方法insert(MIN)
可以获得数组的最低一半。
假设你有o(logN)
(small o notation, better than Theta(logN)
insert 和 O(1) peekMedian()
,那么你得到了一个更好的排序O(NlogN)
,但是排序是个Omega(NlogN)
问题。
=><=
这样insert()
就不能再好O(logN)
了,中位数还在O(1)
。
量子点
EDIT2:修改插入中的中位数:
如果插入前的树大小为 2n+1(奇数),则旧中位数在索引 n+1 处,新中位数在同一索引处(n+1),因此如果在旧中位数之前添加元素 -你需要得到最后一个中位数的前一个节点——这就是新的中位数。如果它是在它之后添加的 - 什么都不做,旧的中位数也是新的中位数。
如果列表是偶数(2n 个元素),那么在插入之后,你应该增加一个索引(从 n 到 n+1),所以如果新元素是在中位数之前添加的 - 什么都不做,如果它是在旧元素之后添加的中位数,您需要将新中位数设置为旧中位数的下一个节点。
注意:这里的next和previous节点是根据key跟随的节点,index表示节点的“位置”(最小的是第一个,最大的是最后一个)。
我只解释了如何插入,同样的想法也适用于删除。