我在这里遇到一个问题,需要设计一个数据结构,该结构在以下三个操作中采用O(lg n)最坏的情况:
a) Insertion: Insert the key into data structure only if it is not already there.
b) Deletion: delete the key if it is there!
c) Find kth smallest : find the ݇k-th smallest key in the data structure
我想知道我是否应该使用堆,但我仍然没有清楚的想法。 我可以轻松地获得O(lg n)中的前两部分,甚至更快但不确定如何处理c)部分。
任何人都有任何想法请分享。
答案 0 :(得分:7)
有两种解决方案:
使用平衡的二进制搜索树(红黑,AVG,Splay,......任何人都可以)。您已熟悉操作(1)和(2)。对于操作(3),只需在每个节点上存储一个额外的值:该子树中的节点总数。您可以轻松地使用此值来查找O(log(n))中的第k个最小元素。 例如,假设您的树如下 - 根A有10个节点,左子B有3个节点,右子C有6个节点(3 + 6 + 1 = 10),假设你想要找到第8个最小元素,你知道你应该去右边。
使用跳过列表。它还支持平均所有(1),(2),(3)O(logn)操作,但实现起来可能要长一些。
答案 1 :(得分:6)
好吧,如果您的数据结构保持元素排序,那么很容易找到第k个最低元素。
答案 2 :(得分:1)
用于搜索和插入的二进制搜索树的最坏情况成本是O(N),而平均情况成本是O(lgN)。
因此,我建议使用红黑二进制搜索树,以保证搜索和插入的最坏情况复杂度为O(lgN)。
您可以阅读有关红黑树here的更多信息,并查看Java here中红黑BST的实现。
因此,在使用上述Red-Black BST实现找到第k个最小元素方面,您只需要调用 select 方法,传入 k 的值。 select 方法也可以保证最坏情况下的O(lgN)。
答案 3 :(得分:0)
其中一个解决方案可能是使用快速排序策略。
步骤1:选择第一个元素作为枢轴元素并将其带到正确的位置。 (最多n次检查) 现在,当您到达此元素的正确位置时,请进行检查
步骤2.1:如果位置> k 您的元素位于第一个子列表中。所以你对第二个子列表不感兴趣。
步骤2.2如果位置
步骤2.3如果位置== k 你有元素打破了外观/递归
步骤3:使用适当的子列表重复步骤1到2.3
此解决方案的复杂性为O(n log n)
答案 4 :(得分:0)
Heap不是用于查找数组的第K个最小元素的正确结构,因为您必须从堆中删除K-1元素才能到达Kth元素。
有一种更好的方法来寻找Kth最小元素,它依赖于中位数算法。基本上任何分区算法平均来说都足够好,但中位数中位数可以证明找到中位数的最坏情况O(N)时间。通常,此算法可用于查找任何特定元素,而不仅仅是中位数。
以下是C#中此算法的分析和实现: Finding Kth Smallest Element in an Unsorted Array
P.S。在相关的说明中,您可以使用数组就地执行许多操作。数组是一个很棒的数据结构,只有当你知道如何在特定情况下组织它的元素时,你可能会非常快速地得到结果并且不需要额外的内存使用。
堆结构是一个很好的例子,QuickSort算法也是如此。这里有一个非常有趣的使用数组的例子(这个问题来自编程奥运会): Finding a Majority Element in an Array