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