【问题标题】:Handle duplicate numbers in kth smallest partition处理第 k 个最小分区中的重复数字
【发布时间】:2018-03-13 02:06:30
【问题描述】:

我已经获得了我的分区算法和 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”整数,我猜该程序由于某种原因不会移动到下一个整数。

感谢您提供的任何帮助!

【问题讨论】:

  • 未引用partitionlast 参数。
  • 你期望上一个例子的输出是什么?
  • @hgminh 输出应该是第 5 个最小的数字。我相信应该是 64。

标签: java arrays recursion


【解决方案1】:

首先,关于partition 函数:

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

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

关于kSmall函数,你的条件p &gt; 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);

【讨论】:

  • 这是非常有用的信息,但我不完全确定如何实现快速排序分区。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
相关资源
最近更新 更多