难度:中等
描述:
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入: n = 3
输出: [[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入: n = 1
输出: [[1]]
提示:
1 <= n <= 20
思路
这道题目可以说在面试中出现频率较高的题目,本题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。
要如何画出这个螺旋排列的正方形矩阵呢?
相信很多同学刚开始做这种题目的时候,上来就是一波判断猛如虎。
结果运行的时候各种问题,然后开始各种修修补补,最后发现改了这里那里有问题,改了那里这里又跑不起来了。
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
由外向内一圈一圈这么画下去。
可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人。
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
那么我按照左闭右开的原则,来画一圈,大家看一下:
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
这也是坚持了每条边左闭右开的原则。
一些同学做这道题目之所以一直写不好,代码越写越乱。
就是因为在画每一条边的时候,一会左开右闭,一会左闭右闭,一会又来左闭右开,岂能不乱。
C语言版代码:
/**
* @brief 59.螺旋矩阵 II
*
* @param n 矩阵的长和宽
* @param returnSize 返回生成的矩阵有多少行
* @param returnColumnSizes 返回矩阵每一行有多少列
*
* @return 螺旋矩阵
**/
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
*returnSize = n;
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
int** matrix = (int**)malloc(sizeof(int*) * n); // 创建二维数组
for (int i = 0; i < n; i++) {
matrix[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
// 初始化四个边界变量,定义当前要填充的"圈"的边界
int t = 0; // top - 上边界
int b = n - 1; // bottom - 下边界
int l = 0; // left - 左边界
int r = n - 1; // right - 右边界
int k = 1; // 要填充的数字,从1开始
while (k <= n * n) {
for (int i = l; i <= r; ++i, ++k) matrix[t][i] = k; // 填充上边(从左到右)
++t; // 填充完成后,上边界t下移一行(++t)
for (int i = t; i <= b; ++i, ++k) matrix[i][r] = k; // 填充右边(从上到下)
--r; // 填充完成后,右边界r左移一列(--r)
for (int i = r; i >= l; --i, ++k) matrix[b][i] = k; // 填充下边(从右到左)
--b; // 填充完成后,下边界b上移一行(--b)
for (int i = b; i >= t; --i, ++k) matrix[i][l] = k; // 填充左边(从下到上)
++l; // 填充完成后,左边界l右移一列(++l)
}
return matrix;
}
完整示例
C语言版:
#include <stdio.h>
#include <stdlib.h>
/**
* @brief 59.螺旋矩阵 II
*
* @param n 矩阵的长和宽
* @param returnSize 返回生成的矩阵有多少行
* @param returnColumnSizes 返回矩阵每一行有多少列
*
* @return 螺旋矩阵
**/
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
*returnSize = n;
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
int** matrix = (int**)malloc(sizeof(int*) * n); // 创建二维数组
for (int i = 0; i < n; i++) {
matrix[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
// 初始化四个边界变量,定义当前要填充的"圈"的边界
int t = 0; // top - 上边界
int b = n - 1; // bottom - 下边界
int l = 0; // left - 左边界
int r = n - 1; // right - 右边界
int k = 1; // 要填充的数字,从1开始
while (k <= n * n) {
for (int i = l; i <= r; ++i, ++k) matrix[t][i] = k; // 填充上边(从左到右)
++t; // 填充完成后,上边界t下移一行(++t)
for (int i = t; i <= b; ++i, ++k) matrix[i][r] = k; // 填充右边(从上到下)
--r; // 填充完成后,右边界r左移一列(--r)
for (int i = r; i >= l; --i, ++k) matrix[b][i] = k; // 填充下边(从右到左)
--b; // 填充完成后,下边界b上移一行(--b)
for (int i = b; i >= t; --i, ++k) matrix[i][l] = k; // 填充左边(从下到上)
++l; // 填充完成后,左边界l右移一列(++l)
}
return matrix;
}
int main() {
int n = 5; // 定义矩阵大小
int returnSize; // 用于接收矩阵的行数
int* returnColumnSizes; // 用于接收每行列数的数组指针
int** resultMatrix; // 用于接收生成的二维矩阵
// 调用函数,注意传递的是地址
resultMatrix = generateMatrix(n, &returnSize, &returnColumnSizes);
// 打印生成的螺旋矩阵
printf("生成的 %dx%d 螺旋矩阵为:\n", n, n);
for (int i = 0; i < returnSize; i++) { // 遍历每一行
for (int j = 0; j < returnColumnSizes[i]; j++) { // 遍历当前行的每一列
printf("%02d ", resultMatrix[i][j]);
}
printf("\n");
}
// !!!重要:释放内存 !!!
for (int i = 0; i < returnSize; i++) {
free(resultMatrix[i]); // 先释放每一行(一维数组)
}
free(resultMatrix); // 再释放存储行指针的数组
free(returnColumnSizes); // 最后释放存储列宽的数组
return 0;
}