如何在 QuickSelect 中实现重复

Posted

技术标签:

【中文标题】如何在 QuickSelect 中实现重复【英文标题】:How to implement duplicates in QuickSelect 【发布时间】:2018-11-11 10:39:58 【问题描述】:

我做了快速选择算法,就是在一个数组中找到第k个最小的数。我的问题是,它只适用于没有重复的数组。 如果我有一个数组

arr = 1,2,2,3,5,5,8,2,4,8,8

它会说第三小的数字是2,但实际上是3。

我不知道该怎么做,这是我的两个方法 quickSelect 和 Partition:

private int quickselect(int[] array, int leftIndex, int rightIndex, int kthSmallest) 

    if(kthSmallest > array.length - 1)
        System.out.print("Number does not exist. Please enter a number less than: ");
        return array.length - 1;
    

    if (leftIndex == rightIndex) 
        return array[leftIndex];
    

    int indexOfPivot = generatePivot(leftIndex, rightIndex);

    indexOfPivot = quickSelectPartition(array, leftIndex, rightIndex, indexOfPivot);

    if (kthSmallest == indexOfPivot) 

        return array[kthSmallest];

     else if (kthSmallest < indexOfPivot) 

        return quickselect(array, leftIndex, indexOfPivot - 1, kthSmallest);

     else 

        return quickselect(array, indexOfPivot + 1, rightIndex, kthSmallest);
    



private int quickSelectPartition(int[] array, int left, int right, int pivotIndex) 

    int pivotValue = array[pivotIndex];

    swapIndexes(array, pivotIndex, right);

    int firstPointer = left;

    for(int secondPointer = left; secondPointer < right; secondPointer++) 

        if(array[secondPointer] < pivotValue) 

            swapIndexes(array, firstPointer, secondPointer);

            firstPointer++;
        
    

    swapIndexes(array, right, firstPointer);

    return firstPointer;

【问题讨论】:

我认为这在O(n)最好的情况下是不可能的了。您可以使用哈希表,但这只会给您预期的时间。 【参考方案1】:

如果将 添加到运行时间是可以接受的,您可以首先将不同的元素复制到一个新数组中:

private int[] getDistinct(int[] array) 
    Set<Integer> distinct = new HashSet<>();
    int endIdx = 0;

    for (int element : array) 

        if (distinct.add(element)) 
            array[endIdx++] = element;
        
    

    return Arrays.copyOfRange(array, 0, endIdx);

然后对其进行快速选择:

int[] arr = new int[] 1, 2, 2, 3, 5, 5, 8, 2, 4, 8, 8;
int kthSmallest = 6;

int[] distinctArray = getDistinct(arr);
int kthSmallestElement = quickselect(distinctArray, 0, distinctArray.length - 1, kthSmallest - 1);

System.out.println(kthSmallestElement);

输出:

8

【讨论】:

QuickSelect 的运行时间是最佳情况和平均情况 O(n),所以我想加上 2N 仍然是 O(n)?

以上是关于如何在 QuickSelect 中实现重复的主要内容,如果未能解决你的问题,请参考以下文章

如何在django模板中实现列表迭代[重复]

如何在网站中实现whatsapp分享按钮[重复]

如何使用对象列表在片段中实现newinstace模式[重复]

如何使用 Traceur 在 ES6 类中实现私有方法 [重复]

如何在没有 Flash 的情况下在 Firefox 中实现复制到剪贴板。需要实施[重复]

快速了解UDP协议