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

77 阅读4分钟

问题描述

小U面临一个有趣的任务:在一个 n×nn×n 的方阵中填入 11 到 n×nn×n 这些数字,并要求按照蛇形顺序从右上角开始,沿着方阵的边界顺时针进行填充。蛇形填充的特殊排列方式使得每一层数字呈现出波浪形的排列方式。

例如,当 n=4n=4 时,方阵应如下所示:

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

你需要编写程序输出填充后的方阵,确保格式的整齐性。


测试样例

样例1:

输入:n = 4
输出:[[10, 11, 12, 1], [9, 16, 13, 2], [8, 15, 14, 3], [7, 6, 5, 4]]

样例2:

输入:n = 5
输出:[[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]]

样例3:

输入:n = 3
输出:[[7, 8, 1], [6, 9, 2], [5, 4, 3]]

解题思路

  1. 矩阵初始化:首先,我们需要初始化一个 n×nn \times n 的二维数组 arr,并将其初始值设为 0,表示这些位置还没有被填充。

  2. 蛇形路径的移动规则:从右上角开始,我们沿着边界顺时针进行填充。顺时针的移动规则依次是:

    • 向下移动
    • 向左移动
    • 向上移动
    • 向右移动 我们可以通过使用一个 flag 变量来控制每次的移动方向,并根据每个方向的移动进行判断。
  3. 填充过程

    • 从右上角(初始位置 (n-1, 0))开始,按顺时针方向填充数字。
    • 需要检查当前位置是否已经被填充,如果已经填充,则调整方向。
    • 每次填充完一个数字后,更新当前位置,并继续填充直到矩阵填满。
  4. 终止条件:当矩阵填充完毕,即所有位置都不为 0 时,停止填充。

代码实现

public class Main {
    public static int[][] solution(int n) {
        // 初始化一个 n x n 的二维数组,默认值为 0
        int[][] arr = new int[n][n];
        
        // 从右上角开始填充
        int x = n - 1, y = 0;
        
        // 初始方向标记,0 表示向下,1 表示向左,2 表示向上,3 表示向右
        int flag = 0, F = 1, count = 1;
        
        // 填充循环,直到所有位置都被填充
        while (true) {
            flag %= 4;  // 保证方向值在 0-3 之间
            while (x < n && y < n && x >= 0 && y >= 0 && arr[y][x] == 0) {
                arr[y][x] = count;  // 填充数字
                count++;  // 更新数字
                F = 0;  // 标记继续填充
                // 根据方向 flag 移动
                switch (flag) {
                    case 0: y++; break;  // 向下
                    case 1: x--; break;  // 向左
                    case 2: y--; break;  // 向上
                    case 3: x++; break;  // 向右
                }
            }
            
            // 如果超出边界,则需要回退并调整方向
            switch (flag) {
                case 0: y--; x--; break;  // 向下 -> 回退到上一个位置
                case 1: x++; y--; break;  // 向左 -> 回退到右上角
                case 2: y++; x++; break;  // 向上 -> 回退到下一个位置
                case 3: x--; y++; break;  // 向右 -> 回退到左下角
            }
            
            // 如果填充完成,则跳出循环
            if (F == 1) break;
            flag++;  // 更改方向
            F = 1;  // 标记完成一圈填充
        }
        
        return arr;  // 返回填充后的矩阵
    }

    public static void main(String[] args) {
        // 测试用例 1
        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}}));

        // 测试用例 2
        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}}));

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

代码解析

  1. 二维数组初始化:我们首先创建了一个 n×nn \times n 的二维数组 arr,并将其所有元素初始化为 0。

  2. 起始点和方向控制:起始点设置在右上角(x = n-1, y = 0)。接着,我们用 flag 来控制填充的方向:初始时 flag = 0 表示向下,flag = 1 表示向左,依此类推。

  3. 填充过程

    • 通过循环填充数字,直到矩阵的每个位置都被填满。
    • 每填充一个数字后,我们根据 flag 来决定填充的方向,并检查当前位置是否已经被填充,如果是,则改变方向。
  4. 结束条件:当 F 被置为 1,表示一圈填充已经完成,可以停止填充。 。