选择:中位数的中位数

时间:2013-05-06 21:02:45

标签: java algorithm sorting

作为一个家庭作业,我被分配编写算法,从无序的数字集中找到第k个有序数。作为一种方法,已经提出了算法median of medians

不幸的是,我的尝试失败了。如果有人发现错误 - 请纠正我。

private int find(int[] A, int size, int k) {
    if (size <= 10) {
        sort(A, 0, size);
        return A[k];
    } else {
        int[] M = new int[size/5];
        for (int i = 0; i < size / 5; i++) {
            sort(A, i*5, (i+1) * 5);
            M[i] = A[i*5 + 2];
        }

        int m = find(M, M.length, M.length / 2);

        int[] aMinus = new int[size];
        int aMinusIndex = 0;
        int[] aEqual = new int[size];
        int aEqualIndex = 0;
        int[] aPlus = new int[size];
        int aPlusIndex = 0;
        for (int j = 0; j < size; j++) {
            if (A[j] < m) {
                aMinus[aMinusIndex++] = A[j];
            } else if (A[j] == m) {
                aEqual[aEqualIndex++] = A[j];
            } else {
                aPlus[aPlusIndex++] = A[j];
            }
        }

        if (aMinusIndex <= k) {
            return find(aMinus, aMinusIndex, k);
        } else if (aMinusIndex + aEqualIndex <= k) {
            return m;
        } else {
            return find(aPlus, aPlusIndex, k - aMinusIndex - aEqualIndex);
        }
    }
}

private void sort(int[] t, int begin, int end) { //simple insertion sort
    for (int i = begin; i < end; i++) {
        int j = i;
        int element = t[i];
        while ((j > begin) && (t[j - 1] > element)) {
            t[j] = t[j - 1];
            j--;
        }
        t[j] = element;
    }
}

我正在运行的测试是输入数字{200,199,198,...,1)并从有序数组中获取第一个数字。我得到了:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -13

由于递归调用而在return A[k]行抛出的内容:

return find(aPlus, aPlusIndex, k - aMinusIndex - aEqualIndex);

3 个答案:

答案 0 :(得分:2)

递归步骤的分支逻辑是向后的。你试图找到第k个最小的数字,你发现有一个小于m的mininIndex数字,aEqualIndex等于m,aPlusIndex大于m。

你应该在aMinus中搜索aMinusIndex&gt; = k,而不是aMinusIndex&lt; = k - 等等。

(通过查看极端情况很容易看到:说小数字小于m。然后显然你不应该在空数组中搜索任何东西,但是因为0 <= k,你将是。)

答案 1 :(得分:0)

我不确切地知道你的问题是什么,但你肯定应该这样做:

sort(A, i*5, (i+1) * 5);

此外,你不应该做那么多的复制,当你这样做时,你没有获得任何表现。该算法应该在适当的位置完成。

查看此维基百科:Selection algorithm

答案 2 :(得分:0)

我知道这是家庭作业,所以你的选择可能受到限制,但我不知道中位数中位数在这里是多么有用。只需使用标准算法对整个数组进行排序,然后选择第k个元素。中位数的中位数有助于找到一个非常好的支点。对于200长度的数据,您不会节省太多时间。

据我所知,你不能准确获得中位数,百分位数或第k个元素,而不是最终排序整个输入数组。使用子集会产生估计值。如果这是错的,我真的很想知道,因为我最近在编写代码来查找数百万个数组中的百分位数!

P.S。可能是因为我不完全理解你的代码...