【问题标题】:How can I visualize what the loop is doing when traversing through a 2D array?遍历二维数组时,如何可视化循环在做什么?
【发布时间】:2021-06-10 11:41:15
【问题描述】:

考虑这段代码:

import java.util.Arrays;

public class Test {
    static int[] getDiagonal(int[][] a) {
        int diagonal[] = new int[a.length];
        for (int i = 0; i < a.length; i++) {
            diagonal[i] = a[i][i];
        }
        System.out.println(Arrays.toString(diagonal));
        return diagonal;
    }

    public static void main(String[] args) {
        int[][] rnd_array = {{1, 2, 4}, {6, 7, 3}, {11, 4, 5}};
        getDiagonal(rnd_array);
    }
}

此代码的目标是获取具有相同行数和列数的二维矩阵的对角线。代码工作得很好,但我不明白如何。我不清楚的部分是我们如何能够只用一个循环遍历二维数组的行和列。我试过用 2 个 for 循环来做,但我没有得到想要的结果。我如何可视化 2D 数组的遍历,我们怎么可能只用 1 个循环遍历它?

【问题讨论】:

  • 你有没有试过在纸上画出你认为数组的每个单元格(你应该看到你用于输入的矩阵)然后单步执行你的代码可能会标记每次迭代中访问的单元格.或者放置一个打印语句,在每次迭代中打印您的 i 值。我认为值得记住你是在增加一个计数器而不是数组,并且 i 只能有值 0,1,2
  • 按下调试按钮
  • 我建议在 intelliJ 中使用调试器,它非常集成并且非常容易理解发生了什么

标签: java arrays loops multidimensional-array


【解决方案1】:

不要把它想象成“数组遍历”,而是遵循 for 循环的实际作用:声明一个变量 i 并在每次迭代后递增它并使用它来访问数组。对于外部数组,您说“给我第一个,第二个,第三个,......元素”(a[i])。这相当于 for each in lists - 你遍历外部数组的所有元素。但是在结果(内部数组)上,您再次访问 ith 元素(a[i][i]) - 这意味着您没有迭代内部数组的 每个 元素,而只是一个 -第一个数组的第一个元素,第二个数组的第二个元素等等。

【讨论】:

    【解决方案2】:

    Java 没有二维数组。它唯一拥有的是一些非常轻量级的语法糖支持,用于制作组件本身就是 1D 数组的 1D 数组。从所有意图和目的来看,这看起来都像是一个 2D 数组,但它也突出了如何“可视化”使用您所谓的“2D 数组”的技巧。

    > int[][] a
    

    这与任何其他数组声明没有什么不同,java 没有二维数组。因此,您应该将其读作X[] a,其中 X 是任何类型。毕竟,您可以创建int[],但您也可以创建String[]List&lt;?&gt;[] - 您可以创建任何类型的数组。在这种情况下,您正在创建一个数组,其组件属于 int[] 类型:一个 int 数组数组。

    要理解的关键点:这些组件数组不需要相同大小!这是完全合法的 java 代码:

    int[][] a = new int[][2];
    // just like any other array of non-primitives,
    // each component slot starts out as null!
    
    System.out.println(a[0]);
    > null
    // see?
    
    a[0] = new int[5];
    System.out.println(Arrays.asList(a[0]));
    > [0, 0, 0, 0, 0]
    a[0][2] = 9;
    System.out.println(Arrays.asList(a[0]));
    > [0, 0, 9, 0, 0]
    

    a[0] 是一个表达式,它解析为a 变量引用的数组的第一个“槽”中的任何内容。紧随其后的[2] 然后将“并给我第三个插槽”应用于您在a[0] 找到的任何内容。所以,a[0][2] 是:通过查看 a 指向的东西的第一个槽,您可以找到数组中的第三个槽。

    a[1] = new int[3]
    

    现在您没有任何意义上的二维数组。因为“2D”数组的第一“行”有 5 个元素,而第二行只有 3 个。

    a = new int[10][10];
    

    这就是我之前告诉过你的轻量语法糖:这只是语法糖:

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

    我不清楚的部分是我们如何能够只用一个循环遍历二维数组的行和列

    这是个好消息!因为您的代码确实遍历二维数组的行和列。它正在做的是击中对角线,并且只击中对角线。

    首先,请意识到这段代码基本上假设您没有像我们之前制作的那样“损坏”的数组——它是一个大小为 X 的数组的数组,并且每个数组组件的大小也是 X。否则它会继续抛出异常。

    确定后,让我们可视化数组中的数组:

    0 1 2
    3 4 5
    6 7 8
    

    那么这段代码只是点击a[0][0]a[1][1]a[2][2]:只有 0、4 和 8。这只有 3 个元素。说得通; 15x15 数组的对角线由 15 个数字组成 - 数学几乎可以解决。因此,在此示例 3x3 数组中,无需遍历 9 个元素来“查找”对角线上的数字。

    如果你真的想运行这段代码,但需要一个完整的循环(这完全是低效的),但只是为了学习:

    for (int x = 0; i < a.length; x++) {
        for (int y = 0; j < a[x].length; y++) {
            if (x == y) {
               // it is on the diagonal!
               diagonal[x] = a[x][y];
            } else {
               // not on the diagonal, so...
               // do not do anything at all.
            }
        }
    }
    

    这也很好用。它只是比较慢,因为它需要检查 n^2 个元素,而不是只查看只需要检查 n 个元素的 a[i][i]

    【讨论】:

    • 哇,多么棒的答案!我现在完全明白了,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 2018-03-09
    • 1970-01-01
    相关资源
    最近更新 更多