这是一道面试题。设计一个类,它存储整数并提供两个操作:
无效插入(int k) 整数 getMedian()
我想我可以使用 BST 来insert
获取 O(logN) 并getMedian
获取 O(logN) (因为getMedian
我应该为每个节点添加左/右子节点的数量)。
现在我想知道这是否是最有效的解决方案,没有更好的解决方案。
这是一道面试题。设计一个类,它存储整数并提供两个操作:
无效插入(int k) 整数 getMedian()
我想我可以使用 BST 来insert
获取 O(logN) 并getMedian
获取 O(logN) (因为getMedian
我应该为每个节点添加左/右子节点的数量)。
现在我想知道这是否是最有效的解决方案,没有更好的解决方案。
您可以使用 2 个堆,我们将调用Left
和Right
。
Left
是一个Max-Heap
。
Right
是一个Min-Heap
。
插入是这样完成的:
x
小于根,Left
那么我们插入x
到Left
.x
到Right
.Left
的元素计数大于 1 的元素计数Right
,则我们调用 Extract-Max onLeft
并将其插入到Right
。Right
的元素计数大于 的元素计数Left
,则我们调用 Extract-MinRight
并将其插入到Left
。中位数始终是 的根Left
。
所以插入是O(lg n)
及时完成的,并且得到中位数是O(1)
及时完成的。
有关涉及两个堆的解决方案,请参阅此Stack Overflow 问题。
如果你在 O < O(log(n) 中选择你的候选人,它会打败一个整数数组吗? ) 并使用一个数组,那么 getMedian 将采用一半大小的索引是 O(1),不是吗?在我看来,比 log(n) + log(n) 做得更好。
另外,通过更灵活一点,您可以通过根据输入属性更改排序算法来提高性能(输入是否几乎已排序......)。
我在计算机科学方面几乎是自学成才,但我会这样做:越简单越好。
您也可以考虑使用自平衡树。如果树是完全平衡的,那么根节点就是你的中位数。比如说,树的一端更深一层。然后,您只需要知道更深的一侧有多少个节点即可选择正确的中位数。