leetcode59.螺旋矩阵II 很绕?理不清?一文给你快速理清思路

🎯 本文详细解析了LeetCode螺旋矩阵II问题的解法。通过一圈一圈填充矩阵的方式,将复杂问题分解为顶行、右列、底行、左列四步操作,每圈填充数量随圈数递减。文中清晰阐述了遍历规律与代码实现逻辑,包括如何确定起点、终点及循环次数,并特别处理了奇数阶矩阵中心元素的填充问题。附带完整Java代码示例,帮助读者理解并掌握这一经典算法题的解决思路。

📖题目📖

题目链接:leetcode.cn/problems/sp...

很多读者看到这道题没理清思路,然后就开始写代码,试来试去提交都有问题。

做这道题,首先需要找一个统一的规律,然后实现起来比较绕,对代码能力也有要求

💱找规律💱

如何填充

  • 一圈一圈来填充(第一圈是浅绿色,第二圈是浅蓝色)
  • 填充一个圈的时候,需要分为四步来操作,即分别填充圈的顶行、右列、底行、左列。假如圈是 n 行 n 列,则顶行、右列、底行、左列 分别填充 n-1 个数。
    • 如第 0 圈,是 5行5列 ,那每一步就填充 4 个数字。
    • 第一步填充 1、2、3、4
    • 第二步填充 5、6、7、8
    • 第三步填充 9、10、11、12
    • 第四步填充 13、14、15、16

从当前圈到下一圈的规律

  • 填充完一圈之后,下一步就是往里面走一圈。
  • 如果当前圈是 n 行 n 列,那往里走一圈就是 n-2 行 n-2 列。姐每往里走一圈,行数、列数都要减 2 。
    • 第 0 圈:5 行 5 列;
    • 第 1 圈:3 行 3 列;
    • 第 2 圈:1 行 1 列

💱如何遍历💱

遍历哪行哪列数据

以顶行填充为例,第 0 圈填充的第 0 行;第 1 圈填充的第 1 行。即第几圈遍历第几行,因此使用一个变量circleNum来表示当前遍历的圈数。

遍历怎么写

如何知道一个循环要怎么写,需要分别确定起点 start 和终点 end。end-start就是循环次数。那我们只要知道 start循环次数即可

java 复制代码
for (int i = start; i < end; i++) {
}
循环次数如何确定

每一步遍历多少个数?

  • 在 5 行 5 列的矩阵填充中,第 0 圈每一步遍历 4 个数,第 1 圈遍历 2 个数,第 2 圈遍历 0 个数(第 2 圈只剩下一个数,不需要遍历处理了,最后额外处理一下就行,不理解直接看代码实现小节)。
  • 即一开始维护一个变量number=n-1,每走完一圈,number减少 2 即可
遍历起点是啥

以顶行为例,第 0 圈从 0 开始遍历,第 1 圈从 1 开始遍历。因此遍历起点是circleNum

java 复制代码
for (int j = circleNum; j < circleNum + number; j++) {
    result[circleNum][j] = ++curNum;
}

右列、底行、左列 规律也依此类推

🧑‍💻代码实现🧑‍💻

代码中 number>0 才继续循环,在 5 行 5 列矩阵中,最后的 25 是没有填充的。那怎么填充这个数字呢?

其实直接设置中间的格子就行

java 复制代码
if (curNum < n * n) {
    result[n / 2][n / 2] = n * n;
}

当然,只有 n 为单数的时候,才需要额外设置。n 为复数的时候,没有漏单的元素,如下图所示

java 复制代码
public static int[][] generateMatrix(int n) {
    int[][] result = new int[n][n];

    // 遍历次数
    int number = n - 1;
    // 走过的圈数
    int circleNum = 0;
    // 当前要填充的数字
    int curNum = 0;

    while (number > 0) {
        /// 顶行填充
        // 第一圈填充的第一行;第二圈填充的第二行
        // 因此,处理第几圈,就是遍历第几行
        for (int j = circleNum; j < circleNum + number; j++) {
            result[circleNum][j] = ++curNum;
        }

        /// 右列填充
        // 第一圈填充的最后一列(n-1);第二圈填充的倒数第二列(n-2)
        // 因此,第几圈,就是倒数第几列
        // 总结为处理 n - circleNum - 1
        for (int i = circleNum; i < circleNum + number; i++) {
            result[i][n - circleNum - 1] = ++curNum;
        }

        // 底行填充
        for (int j = circleNum; j < circleNum + number; j++) {
            result[n - circleNum - 1][n - j - 1] = ++curNum;
        }

        // 左列填充
        for (int i = circleNum; i < circleNum + number; i++) {
            result[n - i - 1][circleNum] = ++curNum;
        }

        // 没转一圈,要遍历的次数就少俩
        number -= 2;
        // 圈数 +1
        circleNum++;
    }

    // --if-- 如果剩下最后一个格子没有填,填充最后一个格子
    if (curNum < n * n) {
        result[n / 2][n / 2] = n * n;
    }

    return result;
}
相关推荐
寻月隐君4 分钟前
探索Web3新速度:Sonic高性能Layer-1上的BlindAuction智能合约实践
后端·web3·github
岁忧21 分钟前
LeetCode 高频 SQL 50 题(基础版)之 【高级字符串函数 / 正则表达式 / 子句】· 上
sql·算法·leetcode
pan_junbiao31 分钟前
Spring框架的设计模式
java·spring·设计模式
远方160932 分钟前
0x-2-Oracle Linux 9上安装JDK配置环境变量
java·linux·oracle
北执南念37 分钟前
CompletableFuture+线程池使用案列
java
天天摸鱼的java工程师41 分钟前
Redis 集群缓存不一致?这篇把坑给你挖明白了
后端
天天摸鱼的java工程师43 分钟前
Redis 除了做缓存还能干什么?
后端
AntBlack1 小时前
Trae Agent :能提高开发效率的功能都值亲自体验一下
后端·ai编程·trae
eachin_z1 小时前
力扣刷题(第四十九天)
算法·leetcode·职场和发展
黄交大彭于晏1 小时前
发送文件脚本源码版本
java·linux·windows