螺旋矩阵详解-java实现

这篇博客介绍了如何使用Java实现从1到n²的所有元素按顺时针顺序螺旋排列的正方形矩阵。代码分析了构建矩阵的过程,包括四个方向的循环、确定每层循环次数以及在不同方向上的变化,并给出了完整的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目(力扣第59题)

给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
在这里插入图片描述

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

分析

1、此题不涉及到什么算法,就是考察对代码的掌控,如何一步一步画出这个矩阵。
首先无论n为多少,结果都是一个方阵,所以我们在写的时候可以想象成多个环套在一起,我们需要从最外部的环开始,一直到最内部的环。

在画每个环时,从左到右,从上到下,从右到左,从下到上,需要不同的循环单独处理;一个环结束,要进入下一层。

四个方向的循环,我们要坚持循环不变量原则,也就是说如下方式:
在这里插入图片描述

每个方向的循环都结束于相同的位置,该行的倒数第二个(图1),尾元素归属下一个方向的循环。图3会导致混乱!
例如:从(0,0)位置开始,最外层,从左到右填充的代码为:

//当前位置
int i = 0, j = 0;
//循环次数
int loop = n==1?1:n-1;
//当前填充的数据
int count = 1;
//标识方向
int direction = 1;
//存放结果
int[][] result = new int[n][n];
while (count <= n * n) {
            //从左往右 direction=1
            if (direction == 1) {
                for (int k = 0; k < loop; ++k) {
                	//设置值后向右移动,同时count自增1
                    result[i][j++] = count++;
                }
                //改变方向,使下次进入从上往下的循环
                direction = 2;
                //结束该次循环
                continue;
            }
            //从上往下 direction=2
            //.....
}

2、接下来是确定每层每个边循环的次数 loop:
在这里插入图片描述

n第一层loop值第二层loop值第三层loop值第四层loop值
321
431
5421
6531
76421
  1. 由代码可知,loop值为循环控制变量;
  2. 我们可以观察到,第一层的loop值,就是初始loop值取决于n的大小,如果n=1,则loop=1,否则loop=n-1
  3. 但是如果当前loop值为2或3,则下一层的loop值一定为1;否则下一层的loop值为loop-2,每一层的各个方向loop值相等;
  4. 所以在每一层的最后一个方向,也就是从下往上赋值结束后,要修改loop;规则参考上述第三点;

3、每一层结束后,都要进入下一层,此时 i,j的值需要重新调整

完整代码及测试

/**
 * question: 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且
 * 元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
 */
public class _59_SpiralMatrix2 {
    public static void main(String[] args) {
        printMatrix(generateMatrix(1));
    }


    public static int[][] generateMatrix(int n) {
        //当前位置
        int i = 0, j = 0;
        //循环次数
        int loop = n == 1 ? 1 : n - 1;
        //当前填充的数据
        int count = 1;
        //标识方向
        int direction = 1;
        //存放结果
        int[][] result = new int[n][n];

        while (count <= n * n) {
            //从左往右
            if (direction == 1) {
                for (int k = 0; k < loop; ++k) {
                    //设置值后向右移动,同时count自增1
                    result[i][j++] = count++;
                }
                //改变方向,使下次进入从上往下的循环
                direction = 2;
                //结束该次循环
                continue;
            }
            //从上往下
            if (direction == 2) {
                for (int k = 0; k < loop; k++) {
                    result[i++][j] = count++;
                }
                direction = 3;
                continue;
            }
            //从右往左
            if (direction == 3) {
                for (int k = 0; k < loop; k++) {
                    result[i][j--] = count++;
                }
                direction = 4;
                continue;
            }
            //从下往上
            if (direction == 4) {
                for (int k = 0; k < loop; k++) {
                    result[i--][j] = count++;
                }
                //方向回到  左----》右
                direction = 1;
                //当前层结束,调整loop
                loop = loop == 3 || loop == 2 ? loop / 2 : loop - 2;
                //i,j指向下一层首个元素
                i++;
                j++;
                continue;
            }

        }
        return result;
    }


    /**
     * 打印矩阵
     *
     * @param matrix
     */
    public static void printMatrix(int[][] matrix) {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + "\t");
            }
            System.out.println();
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值