algorithm - 进行合并排序时是否有必要将索引作为参数传递?

标签 algorithm mergesort

我在网上看到很多mergesort的实现,比如https://www.geeksforgeeks.org/merge-sort/传入参数 l、m 和 r 以了解子数组的开始和结束位置。我想知道如果我们复制子数组并将其传入,运行时和空间复杂度是否会保持不变。示例建议代码如下:

class Solution {

    //mergeSort implementation
    public int[] sortArray(int[] nums) {

        if (nums.length == 1) {
            return nums;
        }

        int arrayLength = nums.length;

        // make copies instead of passing indices
        int[] left = Arrays.copyOfRange(nums, 0, arrayLength/2);
        int[] right = Arrays.copyOfRange(nums, arrayLength/2, arrayLength);

        left = sortArray(left);
        right = sortArray(right);

        return merge(left, right);

    }

    public int[] merge(int[] left,int[] right) {

        int[] merged = new int[left.length + right.length];

        int mergedCounter = 0;
        int i = 0; //leftCounter
        int j = 0; //rightCounter
        while (mergedCounter != left.length + right.length) {
            if (i == left.length) {
                merged[mergedCounter] = right[j];
                mergedCounter++;
                j++;
            } else if (j == right.length) {
                merged[mergedCounter] = left[i];
                mergedCounter++;
                i++;
            } else {
                if (left[i] <= right[j]) {
                    merged[mergedCounter] = left[i];
                    mergedCounter++;
                    i++;
                } else {
                    merged[mergedCounter] = right[j];
                    mergedCounter++;
                    j++;
                }
            }
        }

        return merged;

    }

}

我相信运行的复杂性并没有增加,因为制作一个副本所花费的运行时间与通过 new int[n] 初始化一个 n 长度的新数组所花费的运行时间相同。这部分问题还包括一个 O(n) 合并子函数,所以没关系。

我也相信空间复杂度保持不变。当我们在递归调用中创建两个临时子数组时,将在合并步骤中创建与使用指向 l、m 和 r 的指针的在线解决方案中指定的相同数量的空间。

我的思维过程是否有效,还是我遗漏了什么?

最佳答案

任何额外的复制操作都会增加运行时间。制作子数组的副本将增加一个常数的空间需求,但由于“复杂性”忽略常数和/或低阶项,空间“复杂性”将保持不变。

大多数库使用自下而上合并排序的一些变体,其中索引(或指针)动态更新,而不是通过递归传递,并且通常根据编译器优化保存在寄存器中。自上而下的合并排序主要用作学习练习。

对于自下而上的归并排序,可以通过改 rebase 于归并传递的归并方向,或者对于自上而下的归并排序,基于递归级别来改变归并方向,从而最大限度地减少复制操作。

对于 C/C++,传递数组和索引的替代方法是传递指针或迭代器,将每次调用所需的参数数量减少 1 个参数。

关于algorithm - 进行合并排序时是否有必要将索引作为参数传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56928411/

相关文章:

c# - 如何实现A*算法?

algorithm - 复杂度为 Θ(n^2 log n) 的归并排序算法

java - 如何在没有错误 ArrayIndexOutOfBoundsException 的情况下实现具有 4 向分区的合并排序算法?

java - 如何合并排序具有 O(nlogn) 时间和 O(1) 空间复杂度的链表

c++ - 合并排序 - 段错误

c++ - 计算给定单词在大于 10 亿个单词的文本语料库中出现的次数

algorithm - 在链表中检测循环开始的证明

java - 调用合并排序方法时出现堆栈溢出错误

总结列表及其每个产品的算法?

algorithm - 为什么决策树和 knn 的准确性完全相同(也在特征缩放之后)?