处理第k个最小分区

时间:2018-03-13 02:06:31

标签: java arrays recursion

我已经得到了我的分区算法和ksmall递归方法来计算(几乎)完全...我只是遇到了一个案例,我相信我的分区算法不是随机给出的重复数字阵列。任何其他数组和我的输出都可以正常工作。

递归和分区检查将所有数字小于左侧的枢轴,并且所有数字都大于枢轴,在右侧。

如何处理随机数组中的重复数字?

这是我的代码:

private static int partition(int[] theArray, int first, int last) {
    // Returns the index of the pivot element after partitioning
    // theArray[first..last]

    int p = theArray[first]; // use the first item of the array as the pivot (p)
    int lastS1 = first; // set S1 and S2 to empty
    int lastS2 = theArray.length-1;

    while (lastS1 < lastS2) {
        for (; theArray[lastS1] < p; lastS1++) ;

        for (; theArray[lastS2] > p && lastS2 > 0; lastS2--) ;
        if (lastS1 < lastS2)
            swap(theArray, lastS1, lastS2);
    }
    swap(theArray, lastS1, lastS2);
    return lastS2;
}
public static int kSmall(int k, int[] anArray, int first, int last) {
    int pivotIndex = partition(anArray, first, last);
    int p = anArray[pivotIndex]; // p is the pivot



        if (pivotIndex == k - 1)

            return anArray[pivotIndex];
    if (p > anArray[k - 1])

        return kSmall(k, anArray, first, pivotIndex - 1);

    return kSmall(k, anArray, pivotIndex + 1, last);

在一些示例中进行了更深入的解释:

以下是成功运行的一些示例:

array = [13 | 29 | 53 | 49 | 68 | 12 | 72 | 47 | 80 | 89]
--------------------------------------------------------------------
Please  enter an integer k, 1<=k<=10, or 'R' to refill the array: 
1
Kth smallest is: 12
With K as: 1

和...

array = [60 | 45 | 27 | 20 | 4 | 80 | 75 | 59 | 78 | 41]
--------------------------------------------------------------------
Please  enter an integer k, 1<=k<=10, or 'R' to refill the array: 
1
Kth smallest is: 4
With K as: 1

不成功运行:

array = [68 | 77 | 32 | 54 | 30 | 83 | 68 | 76 | 64 | 30]
--------------------------------------------------------------------
Please  enter an integer k, 1<=k<=10, or 'R' to refill the array: 
5

在这个数组中,有两个'30'整数,我猜这个程序由于某种原因没有转移到下一个。

感谢您提供的任何帮助!

1 个答案:

答案 0 :(得分:1)

首先,关于partition函数:

  • 正如@teppic所提到的,这个函数应该在theArray[first..last]中进行分区。因此,last应分配给lastS2

  • 当所有数组都相同时,您的实现也会失败。在这种情况下,lastS1lastS2永远不会改变,这会导致无限循环。我建议您查看partition的其他一些实现(例如this one - 选择快速排序,右下角部分有伪代码)。

关于kSmall功能,您的条件p > anArray[k - 1]不正确。我们的想法是,在执行分区后,将数组分成两部分pivotIndex。第一部分包含pivotIndex - 1个最小元素,第二部分包含arraySize - pivotIndex个最大元素。使用该信息,您可以决定k最小元素属于哪个部分:

if (pivotIndex == k - 1)
    return a[k - 1];
else if (pivotIndex > k - 1)
    return kSmall(k, a, first, pivotIndex - 1);
else
    return kSmall(k, a, pivotIndex + 1, last);