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 分钟前
Idea集成AI:CodeGeeX开发
java·ai·intellij-idea
杰瑞学AI8 分钟前
LeetCode详解之如何一步步优化到最佳解法:27. 移除元素
数据结构·python·算法·leetcode·面试·职场和发展
jackson凌18 分钟前
【Java学习笔记】运算符
java·笔记·学习
追逐时光者27 分钟前
6种流行的 API 架构风格,你知道几种?
后端
咸鱼求放生31 分钟前
网络请求只到前端页面接口报200并到不到后端接口
java
只会AI搜索得coder38 分钟前
sqlite3 sqlcipher加密,解密,集成springboot,读取sqlcipher加密工具
java·spring boot·sqlite
小麦果汁吨吨吨1 小时前
Flask快速入门
后端·python·flask
kinlon.liu1 小时前
SpringBoot整合Redis限流
spring boot·redis·后端
岩中竹1 小时前
力扣热题100—滑动窗口(c++)
数据结构·c++·算法·leetcode
cg50171 小时前
Spring Boot 中的自动配置原理
java·前端·数据库