将不规则2D数组中的元素合并为一个新的不规则2D数组(深度复制问题)

10

给定两个不规则的数组:a和b,其中a + b总是具有相同的行数:

int[][] a = { {1,2}, {4,5,6} };
int[][] b = { {7}, {8,9,0} };

我要怎样操作一个新的锯齿数组 c 才能返回以下结果:{ {1,2,7}, {4,5,6,8,9,0} }

这是目前我已经有的代码:

int[][] c = null;    
for(int i = 0; i<a.length; i++){
        c = new int[a.length][a[i].length + b[i].length];
}

//rest of my code for assigning the values into the appropriate position works.

正如大家所看到的,问题出在我进行了深拷贝,在for循环的第二次迭代中,将所有行都设置为当前迭代步骤中当前行的长度。

6个回答

4

你的方法存在问题

在循环中,你每次都创建一个新的二维数组对象。每个循环中,你都会重新赋值 c ,从而抛弃了之前的所有工作。此外,在两组方括号中同时放置数字会导致每一行具有相同的长度

使用你的例子,第一次循环时, c 被分配到一个具有两行的二维数组,每行长为三。第二次循环,你抛弃了之前的二维数组并创建了一个新的具有两行的二维数组,每行长为六。

但是,你需要做的是每次循环创建一个新的行,而不是整个二维数组。

解决方法

首先,我们创建一个名为 c 的二维数组,并指定它有 a.length 行。我们不在第二个括号中放置值,因为这将表示所有行的长度相同。因此,此时 c 不知道行长。它只知道它可以有多少行。请记住: c 实际上还没有任何行,只是容纳 a.length 行的容量。

接下来,我们必须创建行并分配长度/容量。我们设置循环的运行次数与行数相同。当前行索引由 i 表示,因此, c [i] 指的是二维 c 数组中的特定行。我们使用 new int [] 来创建每个单独的行/数组,但在方括号内,我们必须指定当前行的长度。对于任何行 c [i] ,其长度由 a [i] 和 b [i] 的长度之和给出;也就是说,《code> a [i] .length + b [i] .length 。

我们最后得到的是一个包含行/数组的数组 c ,每个行/数组的长度/容量都与 a b 中对应行的长度之和相匹配。

请记住, c 仍然不包含任何整数值,只包含正确大小的容器,以容纳 a b 中的值。正如你提到的,你已经有代码填充你的数组了。

int[][] c = new int[a.length][];     

for (int i = 0; i < a.length; i++) {
    c[i] = new int[a[i].length + b[i].length];
}

1
至少要有一个附带解释的答案。好的。 - rpax

3
当初始化Java 2D数组时,可以将其视为一个表格;您只需提供行数,而您的表格的每一行可以具有不同数量的列。
例如,假设我们有一个名为c的2D数组定义如下: int[][] c = new int[10][]; 这意味着您定义了包含10个int[]元素的c。但是,为了使用它,您必须定义每行具有的列数。
例如,假设第二行有3列,则应按以下方式定义: int c[1] = new int[3]; 因此,在此示例中,您需要添加2D数组a和b的列值以计算结果数组,即c。 c[i] = new int[a[i].length + b[i].length]; 这将给您您所期望的结果。
    int[][] a = { {1,2}, {4,5,6} };
    int[][] b = { {7}, {8,9,0} };
    int[][] c = new int[a.length][];    
    for(int i = 0; i<a.length; i++){
            c[i] = new int[a[i].length + b[i].length];
            for (int j=0;j< a[i].length; j++) {
                c[i][j] = a[i][j];
            }
            int length = a[i].length;
            for (int j=0;j< b[i].length; j++) {
                c[i][length+j] = b[i][j];
            }
    }

2
int[][] c = new int[a.length][];    
for(int i = 0; i < c.length; i++){
    c[i] = new int[a[i].length + b[i].length];

    int x = 0;
    for (int num : a[i]) {
        c[i][x] = num;
        x++;
    }
    for (int num : b[i]) {
        c[i][x] = num;
        x++;
    }
}

甚至更简单...
int[][] c = new int[a.length][];    
for(int i = 0; i < c.length; i++){
    c[i] = new int[a[i].length + b[i].length];

    System.arraycopy(a[i], 0, c[i], 0, a[i].length);
    System.arraycopy(b[i], 0, c[i], a[i].length, b[i].length);
}

2
尝试使用c[i] = new int[a[i].length + b[i].length]

我来评论一下这个问题,因为它是最高的,但这也适用于其他发布了几乎相同内容的人:为什么这样做可以解决问题?如果我理解正确,c[i]是行,我们将该行设置为右侧的值,但我不明白这实际上如何解决深度复制问题(你仍然在进行深度复制吗?)。 - csh1579
基本上,当你创建一个二维数组时,你正在创建一个数组的数组,所以c[i]是一个一维数组。我们只在实际拥有该行的值时设置每个单独行的长度一次。如果这不是一个很好的解释,那我很抱歉。你具体是哪方面感到困惑了呢? - SexmanTaco
我会在我的帖子中解释正在发生的事情。 - Joel Christophel

1
尝试这个:

试试这个:

int[][] c = new int[a.length][];
for(int i = 0; i<a.length; i++){ 
    c[i] = new int [a[i].length + b[i].length];
    int j;
    for(j=0; i < a[i].length; j++){
        c[i][j] = a[i][j];
    }
    for(int k=0; i < b[i].length; k++){ 
        c[i][j+k] = b[i][j]; 
    }
} 

0

公共静态无返回值主函数(String [] args) {

 int[][] a = { {1,2}, {4,5,6} };
 int[][] b = { {7}, {8,9,0} };
 int[][] c = null;    
 for(int i = 0; i<a.length; i++){
         c = new int[a.length][a[i].length + b[i].length];
 }

 for(int i = 0; i<a.length; i++){
    for (int j = 0; j < a[i].length+b[i].length; j++) {


    if(j< a[i].length){
        c[i][j]=a[i][j];
    }

    if(j< a[i].length+b[i].length && j>= a[i].length){
        c[i][j]=b[i][j-a[i].length];
    }


    }

 }


 for(int i = 0; i<a.length; i++){
        for (int j = 0; j < a[i].length+b[i].length; j++) {
  System.out.print(c[i][j]);

        }
        System.out.println();
 }

}

这在我的系统中可以运行...........


不,它确实可以工作,但你犯了与OP提出的问题相同的错误。在循环中执行c = new int[a.length][a[i].length + b[i].length];时浪费了内存。请查看其他答案,了解为什么这样做不好。 - sstan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接