【问题标题】:How can i merge three ordered arrays in one ordered array? In O(n)如何将三个有序数组合并到一个有序数组中?在 O(n)
【发布时间】:2019-08-17 08:42:35
【问题描述】:

我的代码应该选择三个数组并返回这三个数组的组合,数组可以有不同的长度。代码应该在 O(n) 中进行组合。

示例:a[] = {1,2} b[] = {1,4,5} c[] = {2,4,5,6}

我的结果应该是:d[] = {1,1,2,2,4,4,5,5,6}

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 我试图创建一个数组 temp 来合并 (a,b) 和另一个数组来合并 (temp,c),但每次合并都是 O(n)。所以我认为我的代码目前在 O(n²) 中运行。
  • 不完全是,记住O(n) + O(n) 仍然 O(n)
  • 我想我明白了! :) 谢谢Glains!

标签: java arrays sorting merge


【解决方案1】:

[在问题编辑中添加 O(n) 约束之前已回答。]

将所有数组添加到列表并再次排序。一个例子是:

Integer[] a = {1, 2};
Integer[] b = {1, 4, 5};
Integer[] c = {2, 4, 5, 6};

List<Integer> lists = new ArrayList<>();
lists.addAll(Arrays.asList(a));
lists.addAll(Arrays.asList(b));
lists.addAll(Arrays.asList(c));

//print
lists
  .stream()
  .sorted()
  .forEach(System.out::println);

【讨论】:

  • 同意@Andy。我没有看到这一点,因为后来编辑了问题并添加了复杂性部分。我的代码复杂度是 O(n log n),因为添加到 arraylist 是 O(1),但排序函数复杂度是 O(n log n)。选择的答案是正确的。谢谢
【解决方案2】:

一种方法(我相信还有很多其他方法)是:

根据输入数组长度之和创建输出数组:

int[] output = new int[a.length + b.length + c.length];

为每个输入数组创建一个索引指针:

int aIndex = 0;
int bIndex = 0;
int cIndex = 0;

为输出数组中的每个位置循环一次,并用每个输入数组的当前索引处的最小值填充它(检查我们没有使用该数组):

for(int outputIndex = 0; outputIndex < output.length; outputIndex++) {
    if (aIndex < a.length
            && (bIndex >= b.length || a[aIndex] <= b[bIndex])
            && (cIndex >= c.length || a[aIndex] <= c[cIndex])) {
        output[outputIndex] = a[aIndex];
        aIndex++;
    } else if (bIndex < b.length
            && (aIndex >= a.length || b[bIndex] <= a[aIndex])
            && (cIndex >= c.length || b[bIndex] <= c[cIndex])) {
        output[outputIndex] = b[bIndex];
        bIndex++;
    } else {
        output[outputIndex] =  c[cIndex];
        cIndex++;
    }
}

编辑:这是我编译和测试的代码:

public class Join {

    public static void main(String[] args) {
        int[] a = {1, 2};
        int[] b = {1, 4, 5};
        int[] c = {2, 4, 5, 6};

        int[] output = new int[a.length + b.length + c.length];

        int aIndex = 0;
        int bIndex = 0;
        int cIndex = 0;

        for(int outputIndex = 0; outputIndex < output.length; outputIndex++) {
            if (aIndex < a.length
                    && (bIndex >= b.length || a[aIndex] <= b[bIndex])
                    && (cIndex >= c.length || a[aIndex] <= c[cIndex])) {
                output[outputIndex] = a[aIndex];
                aIndex++;
            } else if (bIndex < b.length
                    && (aIndex >= a.length || b[bIndex] <= a[aIndex])
                    && (cIndex >= c.length || b[bIndex] <= c[cIndex])) {
                output[outputIndex] = b[bIndex];
                bIndex++;
            } else {
                output[outputIndex] =  c[cIndex];
                cIndex++;
            }
        }
    }
}

在调试器中通过方法末尾的断点进行验证。

【讨论】:

  • 谢谢杰森。我认为它比我的实现更好!我创建了两个数组:一个接收合并(a,b)的临时数组,另一个接收合并(临时,c)的数组。正如 Glains 所说,我的代码 O(n) + O(n) 仍然是 O(n),所以我明白了!
  • 这取决于您的非功能性需求的优先级。除非另有说明,否则以代码清晰(简单)为目标。软件工程中最大的成本之一是维护。我对我复杂的if 语句并不完全满意。就个人而言,我会尝试将它们重构为更简单的东西。如果你的代码比我的更清晰,它可能会更容易维护。
猜你喜欢
  • 2012-05-10
  • 2016-10-22
  • 2017-02-20
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
  • 2016-05-18
相关资源
最近更新 更多