【问题标题】:Is it more efficient to test if an Array is sorted or just sorting it and go from there?测试 Array 是否已排序或仅对其进行排序并从那里开始是否更有效?
【发布时间】:2021-11-21 18:49:39
【问题描述】:

我编写了一个方法来找到我一无所知的数组中的中位数,除了它带有双精度数。它也在工作,但由于我不知道它可能有多大,我想知道我正在做的事情是否有效。 如果数组未排序而不是直接排序,我应该检查它吗? 或者,如果我无论如何都要对它进行排序,那会是一个不必要的步骤吗? 是我推荐的排序方式还是我错过了更好的方式?

//I calculate the median and return it.
public static double median(double[] vals) { //(un-)sorted Array
    double median = 0;

    sortedVals = Arrays.stream(vals).sorted().toArray(); //sorts low to high

    int middleOfArray = (sortedVals.length) / 2 - 1;
    int secondMiddleOfUnevenArray = (sortedVals.length) / 2;

    if(sortedVals.length % 2 == 1) { //uneven values in Array
        median = sortedVals[middleOfArray] + 1;
    } else if(sortedVals.length % 2 == 0) { //even values in Array
        median = (sortedVals[middleOfArray] + sortedVals[secondMiddleOfUnevenArray]) / 2;
    } else {
        System.out.println("Method median: error");
    }
    return median;
}

【问题讨论】:

  • 我猜Arrays.sort(vals) 比流更好的选择
  • 至于检查一个数组是否已经排序,“这会是一个不必要的步骤吗?” - 是的,我同意你的观点,特别是如果你对内容一无所知 - 我会直接去排序。根据用例,您还可以检查零长度数组以避免 sortedVals[middleOfArray] 爆炸
  • 如果您真的关心性能,则根本不需要将数组排序到find a median
  • 任何下降排序库(Java 是)都将具有 O(n) 并且可能对排序输入具有单次扫描性能。因此,运行排序和检查可能需要非常接近同一时间,尤其是在输入很大的情况下,这通常是您唯一关心的情况。

标签: java arrays performance sorting


【解决方案1】:

这似乎是一个基于意见的问题,但从技术上讲,检查输入数组是否已排序可能是有意义的 - 它具有线性 O(N) 复杂度,对于随机输入,只需检查几个元素.

public static boolean isSorted(double ... arr) {
    if (arr == null) {
        return false;
    }   
    int currOrder = 0;
    for (int i = 1; i < arr.length; i++) {
        int nextOrder = Double.compare(arr[i], arr[i - 1]);
        if (currOrder == 0) currOrder = nextOrder;
        if (nextOrder != 0 && nextOrder != currOrder) {
            // System.out.println("Non-sorted at index=" + i + ": " + Arrays.asList(arr[i - 2], arr[i - 1], arr[i])); // log message
            return false;
        }
    }
    
    return true;
}

接下来,对于最小长度为2的数组,中位数似乎存在,所以它的计算需要固定:

public static Double median(double ... vals) { //(un-)sorted Array
    if (vals == null || vals.length < 2) {
        return null; // or throw some exception
    }
    if (!isSorted(vals)) {  // O(N)
        Arrays.sort(vals);  // O(N log N)
    }

    int mid = vals.length / 2;
    if(vals.length % 2 == 1) { //uneven values in Array
        return vals[mid];
    }
    // avoid addition overflow
    return vals[mid - 1] / 2 + vals[mid] / 2;
}

测试:

System.out.println("between max even: " + median(Double.MAX_VALUE, Double.MAX_VALUE));

System.out.println("between max  odd: " + median(Double.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE) + "; MAX=" + Double.MAX_VALUE);

System.out.println("odd : " + median(1, 400, 50, 50, 100000));
System.out.println("even: " + median(1, 3, 50, 100000));
System.out.println("even: " + median(-1, -2, -50, 100000));

输出(启用日志):

between max even: 1.7976931348623157E308
Non-sorted at index=2: [1.7976931348623157E308, 4.9E-324, 1.7976931348623157E308]
between max  odd: 1.7976931348623157E308; MAX=1.7976931348623157E308
Non-sorted at index=2: [1.0, 400.0, 50.0]
odd : 50.0
even: 26.5
Non-sorted at index=3: [-2.0, -50.0, 100000.0]
even: -1.5

【讨论】:

    猜你喜欢
    • 2017-11-20
    • 1970-01-01
    • 2011-12-12
    • 2011-04-06
    • 2011-02-26
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多