快速选择算法中如何处理重复值

7
能否在multiset(值可以重复)上以O(n)的时间复杂度执行查找第k个元素?
因为据我所知,快速选择的想法是使用某个中心点对输入进行分区。然后我有两个数组,我根据正在搜索的索引元素和这两个数组的大小来递归搜索,例如:
1 7 8 5 3 2 4
假设中心点是4,我正在搜索第二大的元素。在分区之后,我可能会得到以下排序:
1 3 2 4 7 8 5
因为右侧子数组包含3个元素,所以我仍将尝试在右侧数组中查找第二大的元素,如果我没错的话?
但是如果我将8作为中心点,我可能会得到如下结果:
1 3 2 7 5 4 8
因此,我将尝试在左表中查找最大的元素(可能是通过线性方式,但通常我会取左子数组并搜索元素-(|右子数组大小| +1))
那么对于multisets呢?假设我有一个数组:
4 5 6 7 7 7 4 3 2 1
我的中心点是6,我正在搜索第3个最大元素,在分区后,我收到了:
4 5 3 2 4 1 6 7 7 7
因此,如果我使用上面提出的方法,我将尝试在右侧子数组上递归执行,而很明显第三个最大值是5,它在左侧?
我想到的唯一解决方案是使用某些数据结构,例如BST、Set等,在O(nlogn)中过滤出重复项。然后使用O(n)快速选择。但是总体而言,这给了我非线性的方法,这可以在线性时间内完成吗?
我还有一个额外的问题,如果无法分配内存怎么办?我能做的就是使用本地整数+堆栈递归。这个问题可以在O(n)中解决吗?因为O(nlogn)可以通过排序+线性“遍历计数”来完成。
1个回答

6
我认为这取决于你对“第k大的元素”的解释。如果你的意思是“在数组中如果排序,排在第k个位置的元素”,那么快速选择算法就可以直接使用,不需要进行修改。
另一方面,如果你的意思是“数组中不同值中第k大的元素”,那么你是正确的,未经修改的快速选择算法将无法正确工作,就像你的示例所展示的那样。然而,你可以通过向哈希表中添加所有元素,然后遍历哈希表以获取每个不同值的一个副本,来修改算法,使其在期望的O(n)时间内工作。从那里,你可以在生成的数组上使用正常的快速选择算法,这将总共需要O(n)的时间。
希望这有所帮助!

说实话,我还没有考虑过HT。但它应该可以工作。无论如何,我也在等待其他建议。如果有的话 :) - abc
我考虑稍微改变一下问题。当分配额外内存不是有效操作时,最快的方法是什么?我只能使用带有元素的开始数组(只能分配O(1)内存+递归堆栈)。这是否可以在nlogn或n中完成?限制意味着我不能使用结构体。 - abc
我自己回答了这个问题,O(nlogn)可以通过简单地对其进行排序并在线性时间内查找有多少相邻值变化来完成。所以这是一个虚拟问题。但仍然存在这样的组合: 无额外内存 + O(n) 是可达到的吗? - abc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接