蛇形填充n阶方阵 | 豆包MarsCode AI刷题

107 阅读3分钟

蛇形填充n阶方阵 | 豆包MarsCode AI刷题

本文通过对Main类中蛇形顺时针矩阵填充代码的剖析,深入理解算法设计思路、Java 多维数组操作及边界处理方法。以下是详细学习内容。


一、问题背景

蛇形顺时针矩阵填充要求在一个 n×nn \times n 的矩阵中,将从 1 到 n2n^2 的数字按特定规则依次填入,规则如下:

  1. 从矩阵的右上角开始填充。
  2. 沿矩阵边界顺时针方向,依次向下、向左、向上、向右填充。
  3. 每次完成一个方向的填充后,根据边界更新规则调整方向,直到填完所有数字。

例如,输入 n=4n = 4 时,输出矩阵为:

10 11 12  1
 9 16 13  2
 8 15 14  3
 7  6  5  4

二、代码解析

以下代码完成了上述任务,分为函数实现部分和测试部分。

1. 函数实现部分
public static int[][] solution(int n) {
    int[][] arr = new int[n][n]; // 初始化一个 n × n 的矩阵
    int temp = 1;                // 当前填充的数字
    int top = 0, bottom = n - 1, left = 0, right = n - 1; // 定义矩阵四个边界

    while (temp <= n * n) {      // 当未填满矩阵时循环
        // 向下填充一列
        for (int i = top; i <= bottom; i++) {
            arr[i][right] = temp++;
        }
        right--;  // 右边界左移

        // 向左填充一行
        for (int j = right; j >= left; j--) {
            arr[bottom][j] = temp++;
        }
        bottom--; // 下边界上移

        // 向上填充一列
        for (int i = bottom; i >= top; i--) {
            arr[i][left] = temp++;
        }
        left++;   // 左边界右移

        // 向右填充一行
        for (int j = left; j <= right; j++) {
            arr[top][j] = temp++;
        }
        top++;    // 上边界下移
    }

    return arr;  // 返回填充好的矩阵
}

核心步骤解析

  • 初始化边界和填充变量top, bottom, left, right 分别表示上下左右边界,初始值覆盖整个矩阵范围。

  • 方向控制与循环:通过while循环依次完成 4 个方向的填充,并在每个方向填充后更新边界,防止重复覆盖。

  • 数字填充逻辑

    • 向下:遍历当前右边界所在的列,逐行填入数字。
    • 向左:遍历当前下边界所在的行,从右向左填入数字。
    • 向上:遍历当前左边界所在的列,逐行逆序填入数字。
    • 向右:遍历当前上边界所在的行,从左向右填入数字。
  • 边界收缩:每完成一个方向的填充,对应的边界向内收缩一格,确保后续填充不出界。


2. 测试部分
public static void main(String[] args) {
    int[][] a1 = solution(4);
    System.out.println(java.util.Arrays.deepEquals(a1, new int[][]{
        {10, 11, 12, 1},
        {9, 16, 13, 2},
        {8, 15, 14, 3},
        {7, 6, 5, 4}
    }));

    int[][] a2 = solution(5);
    System.out.println(java.util.Arrays.deepEquals(a2, new int[][]{
        {13, 14, 15, 16, 1},
        {12, 23, 24, 17, 2},
        {11, 22, 25, 18, 3},
        {10, 21, 20, 19, 4},
        {9, 8, 7, 6, 5}
    }));

    int[][] a3 = solution(3);
    System.out.println(java.util.Arrays.deepEquals(a3, new int[][]{
        {7, 8, 1},
        {6, 9, 2},
        {5, 4, 3}
    }));
}

测试解析

  • 测试函数利用java.util.Arrays.deepEquals验证生成的矩阵是否与预期结果相等。
  • 测试了 n=4n = 4、n=5n = 5、n=3n = 3 三种不同规模矩阵,覆盖了基本情况。

三、扩展与总结

  1. 时间复杂度:填充每个元素需要 O(1)O(1) 时间,总共有 n2n^2 个元素,因此时间复杂度为 O(n2)O(n^2)。
  2. 空间复杂度:矩阵需要 O(n2)O(n^2) 空间,额外变量边界和填充计数器的空间需求为 O(1)O(1)。
  3. 改进方向:该代码逻辑清晰,直接操作边界更新。若需提升代码复用性,可将方向控制部分抽象为函数。

通过本例学习,可以掌握矩阵边界操作与多维数组的填充技巧,同时理解了如何利用逻辑控制边界更新,实现复杂矩阵操作任务。