数组5:螺旋矩阵II(59)
本题如下:(链接:https://leetcode.cn/problems/spiral-matrix-ii/)
题目:
给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
思路:
这题在算法上其实没什么,主要还是其模拟过程比较复杂。
我们知道如果要写出正确的二分法一定要坚持循环不变量原则。同样地,求解本题依然是要坚持循环不变量原则。
模拟顺时针画矩阵的过程:填充上行从左到右,填充右列从上到下,填充下行从右到左,填充左列从下到上
由外向内一圈一圈这么画下去。我们可以发现这里的边界条件非常多,这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
以下图为例:
该图中的每一种颜色,代表一条边,我们遍历的长度。可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续处理。这也是坚持了每条边左闭右开的原则。
C++代码如下,已经详细注释了每一步的目的,可以看出while循环里判断的情况是很多的,代码里处理的原则也是统一的左闭右开。
1 class Solution { 2 public: 3 vector<vector<int>> generateMatrix(int n) { 4 vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组 5 int startx = 0, starty = 0; // 定义每循环一个圈的起始位置 6 int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理 7 int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2) 8 int count = 1; // 用来给矩阵中每一个空格赋值 9 int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位 10 int i,j; 11 while (loop --) { 12 i = startx; 13 j = starty; 14 15 // 下面开始的四个for就是模拟转了一圈 16 // 模拟填充上行从左到右(左闭右开) 17 for (j = starty; j < n - offset; j++) { 18 res[startx][j] = count++; 19 } 20 // 模拟填充右列从上到下(左闭右开) 21 for (i = startx; i < n - offset; i++) { 22 res[i][j] = count++; 23 } 24 // 模拟填充下行从右到左(左闭右开) 25 for (; j > starty; j--) { 26 res[i][j] = count++; 27 } 28 // 模拟填充左列从下到上(左闭右开) 29 for (; i > startx; i--) { 30 res[i][j] = count++; 31 } 32 33 // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1) 34 startx++; 35 starty++; 36 37 // offset 控制每一圈里每一条边遍历的长度 38 offset += 1; 39 } 40 41 // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值 42 if (n % 2) { 43 res[mid][mid] = count; 44 } 45 return res; 46 } 47 };
下面放一下该题的Java版本:
1 class Solution { 2 public int[][] generateMatrix(int n) { 3 int loop = 0; // 控制循环次数 4 int[][] res = new int[n][n]; 5 int start = 0; // 每次循环的开始点(start, start) 6 int count = 1; // 定义填充数字 7 int i, j; 8 9 while (loop++ < n / 2) { // 判断边界后,loop从1开始 10 // 模拟上侧从左到右 11 for (j = start; j < n - loop; j++) { 12 res[start][j] = count++; 13 } 14 15 // 模拟右侧从上到下 16 for (i = start; i < n - loop; i++) { 17 res[i][j] = count++; 18 } 19 20 // 模拟下侧从右到左 21 for (; j >= loop; j--) { 22 res[i][j] = count++; 23 } 24 25 // 模拟左侧从下到上 26 for (; i >= loop; i--) { 27 res[i][j] = count++; 28 } 29 start++; 30 } 31 32 if (n % 2 == 1) { 33 res[start][start] = count; 34 } 35 36 return res; 37 } 38 }
本文来自博客园,作者:Ricentch,转载请注明原文链接:https://www.cnblogs.com/cnwsh/p/16561147.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构