【问题标题】:How to implement randomized O(n) algorithm for finding median of unsorted array in Java?如何实现随机 O(n) 算法以在 Java 中查找未排序数组的中位数?
【发布时间】:2019-03-05 14:51:29
【问题描述】:

我有这段代码用于在 O(n) 预期时间(最坏情况 O(n^2) 中查找未排序数组的中位数)。我使用 long 是因为我希望能够保存 long 值。

public class Randomized {

    long kthSmallestHelper(long arr[], long l, long r, long k) 
    { 
        if (k > 0 && k <= r - l + 1) 
        { 
            long pos = randomPartition(arr, l, r); 

            if (pos-l == k-1) 
                return arr[(int)pos]; 

            if (pos - l > k - 1) 
                return kthSmallestHelper(arr, l, pos - 1, k);

            return kthSmallestHelper(arr, pos + 1, r, k - pos + l - 1); 
        } 
          return Integer.MAX_VALUE; 
    } 

    void swap(long arr[], long i, long j) 
    { 
        long temp = arr[(int)i]; 
        arr[(int)i] = arr[(int)j]; 
        arr[(int)j] = temp; 
    } 

    long partition(long arr[], long l, long r) 
    { 
        long x = arr[(int)r], i = l; 
        for (long j = l; j <= r - 1; j++) 
        { 
            if (arr[(int)j] <= x) 
            { 
                swap(arr, i, j); 
                i++; 
            } 
        } 
        swap(arr, i, r); 
        return i; 
    } 

    long randomPartition(long arr[], long l, long r) 
    { 
        long n = r - l + 1; 
        long pivot = (long)(Math.random()) * (n - 1); 
        swap(arr, pivot + 1, r); 
        return partition(arr, l, r); 
    } 

    long kthSmallestRandom(long arr[], long k){
        return kthSmallestHelper(arr, 0, arr.length - 1, k);

    }

}

但是当我运行它时

    long[] array =  {12, 3, 5, 7, 4, 19, 26}; //median is 7
    Randomized rand = new Randomized();
    System.out.println(rand.kthSmallestRandom(array, (array.length + 1)/2));

不正确(返回 4)。

我的想法是使用这个版本的第 k 个最小数字来表示我想要第 (length/2)th 最小的数字,即中位数。

我的想法或实现有什么问题?

【问题讨论】:

  • 对数组进行排序然后选择中间元素不是更好吗?您可以使用 O(n*log(n)) 中的内置方法对数组进行排序

标签: java algorithm sorting median


【解决方案1】:

你的kthSmallestHelper函数在这一行有一个小错误:

if (pos-l == k-1) 
    return arr[(int)pos];

返回使用了错误的索引。尝试pos-l+1 而不是pos(并将其转换为int)。这将返回第 k 个项目,该项目刚刚排序到数组中的正确位置。

【讨论】:

    【解决方案2】:

    我无法运行它,但目前似乎有很多问题。

    在 Java 中,当您将数组传递给函数时,只会传递数组的副本,因此您所做的任何交换都不会在该方法之外更改数组。看起来你的分区也关闭了。而不是传入分区,你只是传入左右边界,看起来你的分区方法只将东西发送到分区的左侧。

    应该对这段代码进行更多注释,以便我们可以了解您在每个点上要执行的操作。另外,由于您将事物交换为排序顺序,因此看起来像 O(nlogn) ,因为您无法在线性时间内进行排序。为什么不能使用 k == 0 作为第 k 个最小的助手?

    【讨论】:

    • “在 Java 中,当您将数组传递给函数时,只会传递数组的副本,”不是这样。数组是引用类型,就像所有其他类一样。
    【解决方案3】:

    我不知道为什么,但只是将所有 long 更改为 int 即可修复它。它现在按预期工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多