59.螺旋矩阵II
59.1 题目
给你一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix。
示例 1:

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1
输出:[[1]]
提示:
1 <= n <= 20
59.2 题解
方法一:逐层模拟
思路
与第54题类似,用四个边界指针 top、bottom、left、right 标记当前填充范围。按顺时针方向依次填充:从左到右、从上到下、从右到左、从下到上。每填充完一层,边界向内收缩,直到填满所有元素。用变量 nowVal 记录当前要填充的数字,从1递增到 n²。
核心思想:四边界逐层填充,顺时针方向。
具体步骤:
- 创建
n × n矩阵,初始化边界指针。 - 当
top <= bottom && left <= right时:- 从左到右填充上边界
- 从上到下填充右边界
- 从右到左填充下边界(需检查
top < bottom) - 从下到上填充左边界(需检查
left < right)
- 收缩边界,继续下一层。
举例:对于 n = 3:
- 第一层:上
[1,2,3],右[4,5],下[6,7],左[8] - 第二层:中心
[9] - 结果:
[[1,2,3],[8,9,4],[7,6,5]]
复杂度分析
- 时间复杂度:
O(n²),需要填充n²个元素。 - 空间复杂度:
O(1),除结果矩阵外只使用常数空间。
代码
// 方法一:逐层模拟
// 大致思路和54题一致
// 区别是要创建一个要返回的nxn交错数组,设置行列都为n
// 定义索引用于填充交错数组
static int[][] GenerateMatrix1(int n)
{
// 如果 n 为 1,直接返回一个包含 1 的二维数组
if (n == 1)
{
return new int[][] { new[] { 1 } };
}
// 创建一个 n x n 的二维数组
int[][] resultMatrix = new int[n][];
// 初始化二维数组的每一行
for (int i = 0; i < n; i++)
{
resultMatrix[i] = new int[n];
}
// 初始化四个边界指针,表示当前螺旋填充的上、下、左、右边界
int top = 0;
int left = 0;
int right = n - 1;
int bottom = n - 1;
// 初始化当前要填充的数字
int nowVal = 1;
// 当上边界小于等于下边界且左边界小于等于右边界时,继续填充
while (top <= bottom && left <= right)
{
// 从左到右填充当前行
for (int i = left; i <= right; i++)
{
resultMatrix[top][i] = nowVal++;
}
// 从上到下填充当前列
for (int i = top + 1; i <= bottom; i++)
{
resultMatrix[i][right] = nowVal++;
}
// 检查是否有足够的行和列使得可以从右到左填充
if (left < right && top < bottom)
{
// 从右到左填充当前行
for (int i = right - 1; i >= left; i--)
{
resultMatrix[bottom][i] = nowVal++;
}
// 从下到上填充当前列
for (int i = bottom - 1; i > top; i--)
{
resultMatrix[i][left] = nowVal++;
}
}
// 更新边界指示器,缩小螺旋填充范围
top++;
left++;
bottom--;
right--;
}
// 返回生成的二维数组
return resultMatrix;
}
59.3 代码
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
#region 题目
// 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
// 示例 1:
// 输入:n = 3
// 输出:[[1,2,3],[8,9,4],[7,6,5]]
// 示例 2:
// 输入:n = 1
// 输出:[[1]]
#endregion
#region 测试
// 示例 1
int n1 = 3;
int[][] resultMatrix1 = GenerateMatrix1(n1);
Console.WriteLine($"示例1 方法1 输出:");
PrintMatrix(resultMatrix1);
// 示例 2
int n2 = 1;
int[][] resultMatrix2 = GenerateMatrix1(n2);
Console.WriteLine($"示例2 方法1 输出:");
PrintMatrix(resultMatrix2);
#endregion
}
#region 答案
// 方法一:逐层模拟
// 大致思路和54题一致
// 区别是要创建一个要返回的nxn交错数组,设置行列都为n
// 定义索引用于填充交错数组
static int[][] GenerateMatrix1(int n)
{
// 如果 n 为 1,直接返回一个包含 1 的二维数组
if (n == 1)
{
return new int[][] { new[] { 1 } };
}
// 创建一个 n x n 的二维数组
int[][] resultMatrix = new int[n][];
// 初始化二维数组的每一行
for (int i = 0; i < n; i++)
{
resultMatrix[i] = new int[n];
}
// 初始化四个边界指针,表示当前螺旋填充的上、下、左、右边界
int top = 0;
int left = 0;
int right = n - 1;
int bottom = n - 1;
// 初始化当前要填充的数字
int nowVal = 1;
// 当上边界小于等于下边界且左边界小于等于右边界时,继续填充
while (top <= bottom && left <= right)
{
// 从左到右填充当前行
for (int i = left; i <= right; i++)
{
resultMatrix[top][i] = nowVal++;
}
// 从上到下填充当前列
for (int i = top + 1; i <= bottom; i++)
{
resultMatrix[i][right] = nowVal++;
}
// 检查是否有足够的行和列使得可以从右到左填充
if (left < right && top < bottom)
{
// 从右到左填充当前行
for (int i = right - 1; i >= left; i--)
{
resultMatrix[bottom][i] = nowVal++;
}
// 从下到上填充当前列
for (int i = bottom - 1; i > top; i--)
{
resultMatrix[i][left] = nowVal++;
}
}
// 更新边界指示器,缩小螺旋填充范围
top++;
left++;
bottom--;
right--;
}
// 返回生成的二维数组
return resultMatrix;
}
#endregion
#region 辅助函数
// 打印矩阵
static void PrintMatrix(int[][] matrix)
{
foreach (var row in matrix)
{
Console.Write("[");
// 使用 Join 方法将每个数字连接起来,逗号分隔
Console.Write(string.Join(", ", row));
Console.WriteLine("]");
}
}
#endregion
}
59.4 运行结果
示例1 方法1 输出:
[1, 2, 3]
[8, 9, 4]
[7, 6, 5]
示例2 方法1 输出:
[1]
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com