创建一个中位数数组。爪哇

时间:2020-02-21 14:56:17

标签: java arrays algorithm loops for-loop

我在寻找本练习的解决方案时遇到了麻烦:

Given scores, an array of integers representing all test and assignment scores, your task is to return an array of integers where output[i] represents the median grade after all marks up to (and including) scores[i] have been entered. Your instructor is a generous marker, so they always round the median up to the nearest integer.

median* - The median of an N-element sequence is defined as follows: If N is odd, the median is the element which stands in the middle of the sequence after it is sorted. If N is even, the median is the average (mean) of the two "middle" elements of the sequence after it is sorted.

Example

•For scores = [100, 20, 50, 70, 45] the output should be medianScores(scores) = [100, 60, 50, 60, 50].

After each score is entered, the median is recalculated as follows:
◦For [100], the median is 100 since it's the only element.
◦For [20, 100], the median is (20 + 100)/2 = 60 since there's an even number of elements.
◦For [20, 50, 100], the median is 50 (middle element).
◦For [20, 50, 70, 100], the median is (50 + 70)/2 = 60(mean of the two middle elements).
◦For [20, 45, 50, 70, 100], the median is 50 again (middle element).


Input / Output

我一直在尝试获取有效的代码,到目前为止,如果数组的长度为奇数,但即使它的偶数返回错误结果,该代码也可以工作;

 public static int[] getMedian(int[] arr){

    int[] sortedArr = new int[arr.length];
    int length = arr.length-1;
    int odd = arr.length-1;
    int even = arr.length-1;

    for(int i=0;i<arr.length;i++) {

        sortedArr[length] = arr[i];
        Arrays.sort(sortedArr);

        if (length % 2 == 0) {
            arr[i] = sortedArr[odd];
            odd--;
        } else {
            arr[i] = (sortedArr[even] + sortedArr[even - 1]) / 2;
            even--;
        }
        length--;
    }
return arr;

}

该算法通过将arr中的元素添加到sortedArr中来工作。对元素进行排序,然后检查sortedArr是偶数还是奇数。如果其偶数arr [i]成为中间元素,如果其奇数arr [i]是中间元素之和除以2。

请您帮忙。

3 个答案:

答案 0 :(得分:1)

将数组复制到sortedArray时,您正在覆盖现有值。

    public static void main(String[] args) {
        int[] ret = getMedian(new int[]{100,20,50,70,45});
        System.out.println(Arrays.toString(ret));
    }

    public static int[] getMedian(int[] arr) {

        int[] sortedArr = new int[arr.length];
        int[] retArr = new int[arr.length];
        int len = 1;
        int realLength = arr.length-1;

        for (int i = 0; i < arr.length; i++) {

            sortedArr[realLength-i] = arr[i];
            Arrays.sort(sortedArr);
           // arrays are accessed in reverse so adjust is needed using
           // array length.
            if (len % 2 == 1) {
                // use middle value
                retArr[i] = sortedArr[realLength-len/2];
            } else {
                // average middle values 
                retArr[i] = (sortedArr[realLength-len/2]
                        + sortedArr[realLength-len/2 + 1]) / 2;
            }
            len++;
        }
        return retArr;
    }

}

答案 1 :(得分:1)

未优化的解决方案。

首先是一种只计算数组中位数的方法:

/** Generous or not: one to round up, zero to round down. */
private static final int generous = 1;

private static int median(int[] arr) {
    Arrays.sort(arr);
    int mid = arr.length / 2;
    if (mid + mid == arr.length) { // little optimized "is it even"
        return (arr[mid-1] + arr[mid] + generous) / 2;
    } else {
        return arr[mid];
    }
}

然后为每个子数组调用它:

// passed array will be (partially) sorted
private static int[] getMedian(int[] arr) {
    int[] result = new int[arr.length];
    for (int i = 0; i < arr.length; i++) {
        result[i] = median(Arrays.copyOfRange(arr, 0, i+1));
    }
    return result;
}

最优化:不创建子数组,只需传递要考虑的长度

private static int median(int[] arr, int len) {
    Arrays.sort(arr, 0, len);
    int mid = len / 2;
    if (mid + mid == len) { // little optimized "is it even"
        return (arr[mid-1] + arr[mid] + generous) / 2;
    } else {
        return arr[mid];
    }
}
getMedian()

称为

result[i] = median(arr, i+1);

答案 2 :(得分:1)

为了提高效率,第一步是确定更好的算法。

让我们调用median[]创建的数组。

我将使用两个堆:

  • leftk/2的最小值的最大堆k/2+1直至第k个索引,取决于k是偶数还是奇数。
  • right的最小值堆k/2直至第k个索引为止

然后

if k is even, median[k] = (left.max() + right.min())/2
if k is odd, median[k] = left.max()

初始化:

left <- min (scores[0], scores[1])
right <- max (scores[0], scores[1])

然后,对于每个新值x = scores[k],您必须管理两个堆,具体取决于k是偶数还是奇数,并取决于x,{{1 }}和left.max()。两个堆保持正确的大小非常重要。这意味着有时值会从一个堆移到另一个堆。

如果right.min()是偶数(k是奇数):

k-1

如果If x < left.max() then x -> left, left.max() -> right (corresponding value removed from left) else: x -> right 为奇数:

k

全局复杂度:O(nlogn)

我不太了解Java。如果Java没有堆,我想您可以改用If x < right.min() then x -> left else: x -> right, right.min() -> left (corresponding value removed from right)