当前位置: 首页 > 知识库问答 >
问题:

测试数组是否已排序或仅对其进行排序并从那里开始更有效?

阎承
2023-03-14

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

//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;
}

共有1个答案

阳文轩
2023-03-14

这似乎是一个基于意见的问题,但从技术上讲,检查输入数组是否排序是有意义的 - 它具有线性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
 类似资料:
  • 问题内容: 假设我们在集合中有一些项目,并且我们想使用某些比较器对它们进行排序,并期望结果在列表中: 一种方法是对列表中的项目进行排序,例如: Anothe方法正在使用排序流: 我想知道哪种方法更有效?排序流是否有任何优势(例如在多核上进行Faste排序)? 在运行时复杂性方面/最快方面是高效的。 我不相信自己要实现一个完美的基准,学习并不能真正启发我。 问题答案: 可以肯定地说,两种形式的排序都

  • 问题内容: 假设我有一个自定义类的数组,每个类都包含一个名为 我还有一个任意值数组,称为,如下所示: 我的目标是对所有QB 进行排序,然后再对所有WR,RB和TE 进行排序。 我当前的操作方式是遍历中的每个元素,然后遍历所有播放器以附加到新数组。但是,我想不出一种更简单(更有效)的方法来做到这一点。非常感谢任何提示或指示。谢谢。 问题答案: 编辑: 我原来的方法是狗屎。这篇文章吸引了很多人的注意力

  • 问题内容: 是否可以使用排序数组,然后再将另一个相关数组定位为与排序数组相同,例如: 从这一点出发,我想对数组进行排序,这样,如果“人”有一个cellNo“ x”,则在对数组进行排序后,他将具有相同的“ cellNo”“ x” 问题答案: 我会采用另一种方法: 创建一个新对象: 创建一个比较器: 打电话一对阵列

  • 对于这个项目,我得到了一个字符串数组和一个整数数组。int[1]是字符串[1]的排名。我需要使用mergesort按1到n的顺序对int数组进行排序,我在下面已经完成了这项工作。但是当int数组被移动时,我还需要切换字符串数组的位置,以便它们都被排序,如果这有意义的话?我不知道我的编码有什么问题,甚至我的想法是否真的有效,但我一直在stringSorted[k]=stringRight[j]上得到

  • 问题内容: 令我惊讶的是,以前没有提出过这个具体问题,但我的确没有在SO或文档中找到它。 假设我有一个包含整数的随机numpy数组,例如: 如果对它进行排序,则默认情况下我将获得升序: 但我希望解决方案按 降序 排序。 现在,我知道我可以永远做: 但这最后的陈述 有效 吗?它不是按升序创建副本,然后反转此副本以反转顺序获得结果吗?如果确实如此,是否有有效的选择?看起来好像不接受参数来更改排序操作中

  • 我想按第三个和第一个元素对元组数组进行排序,因此我使用了以下代码: 我的问题是,在前面的例子中,我可以按第三个元素和第一个元素的升序排序,也可以按它们的降序排序(使用反向)。但是如何按第三个元素的升序和第一个元素的降序排序。 请在你的回答中考虑以下情况: 在这种情况下,我不知道内部数组的确切大小(取决于我读入该数组的文件模式),我想按侧中的所有项进行排序(一些升序和一些降序)。 编辑:看起来,我明