LeetCode 59. 螺旋矩阵 II
题目描述
:::fold 历史考题
考察公司:小米
:::


题意分析
创建一个
n × n的正方形矩阵,把整数1到n²按顺时针螺旋顺序填入:从左上角开始向右,沿外圈依次转向下、左、上,再进入内圈继续。每个数使用一次,每个格子也只填写一次。目标是生成矩阵,不是从已有矩阵读取元素;奇数边长最后会剩一个中心格,也需要按顺序写入。
解法:四边界螺旋填充
核心思路
[!blue]
不必为每个格子单独记录是否访问过。用
top、bottom、left、right四个边界描述尚未填写的矩形,边界外都已完成;用value保存下一个要写入的数。每轮依次处理当前矩形的上、右、下、左四条边。写完上边后立刻
top++,右边就从新的上边界开始,不会再次覆盖右上角。写完右边后立刻right--,下边也使用新的右端点;下边、左边同理。因为每条边写完便被移出未处理区域,相邻两条边即使原本共享拐角,后处理的一边也不再包含它。这样保证不重复;每轮剩下的又是更小的矩形,所以继续套用相同流程,就不会遗漏内圈。
当剩余区域只是一行、一列或一个中心格时,一轮未必还存在四条不同的边。代码在下边和左边前检查边界,并让所有循环使用已经收缩的范围;没有剩余格子时循环区间为空,不会再次写入。上下或左右边界交叉后,整个矩阵已经填完。
解题步骤
- 创建
n × n的矩阵,四条边界初始化为最外圈,令value = 1。- 在上下、左右边界均未交叉时,从左到右填写上边,每写一格递增
value,随后将上边界下移。- 从新的上边界向下填写右边,随后将右边界左移。
- 若上下边界仍有效,从右到左填写下边,再将下边界上移。
- 若左右边界仍有效,从下到上填写左边,再将左边界右移。
- 继续处理内圈,边界交叉后返回矩阵。
代码实现
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
int top = 0;
int bottom = n - 1;
int left = 0;
int right = n - 1;
int value = 1;
while (top <= bottom && left <= right) {
for (int col = left; col <= right; col++) {
matrix[top][col] = value++;
}
// 一条边填完立即收缩,下一条边使用更新后的端点。
top++;
for (int row = top; row <= bottom; row++) {
matrix[row][right] = value++;
}
right--;
if (top <= bottom) {
for (int col = right; col >= left; col--) {
matrix[bottom][col] = value++;
}
bottom--;
}
if (left <= right) {
// 左边界仍存在时,再从下到上填充左边。
for (int row = bottom; row >= top; row--) {
matrix[row][left] = value++;
}
left++;
}
}
return matrix;
}
}
func generateMatrix(n int) [][]int {
matrix := make([][]int, n)
for i := 0; i < n; i++ {
matrix[i] = make([]int, n)
}
top := 0
bottom := n - 1
left := 0
right := n - 1
value := 1
for top <= bottom && left <= right {
for col := left; col <= right; col++ {
matrix[top][col] = value
value++
}
// 一条边填完立即收缩,下一条边使用更新后的端点。
top++
for row := top; row <= bottom; row++ {
matrix[row][right] = value
value++
}
right--
if top <= bottom {
for col := right; col >= left; col-- {
matrix[bottom][col] = value
value++
}
bottom--
}
if left <= right {
// 显式检查剩余列范围,再按收缩后的边界填充左侧。
for row := bottom; row >= top; row-- {
matrix[row][left] = value
value++
}
left++
}
}
return matrix
}
复杂度分析
- 时间复杂度:$O(n^2)$。每个格子恰好填写一次,且输出本身就有
n²个元素。- 空间复杂度:$O(1)$。除返回矩阵外只使用四条边界和一个计数器。
关键点总结
[!green]
- 四条边界表示剩余未填区域,不是最初矩阵边界,后续循环必须使用更新后的值。
- 每填完一边立即收缩,对应的拐角不会再出现在下一条边中。
- 剩余区域不断缩小直到为空,从而保证每个格子都被且只被填入一次。
易错点总结
[!yellow]
- 填下一条边时仍使用旧起点,会重新写入刚处理过的拐角,并导致后面的数全部错位。
- 写完边后忘记收缩,会重复处理同一区域,甚至无法结束。
- 向左或向上时仍递增下标,会破坏顺时针顺序或越界。
- 无视剩余区域是否为空,会在单行、单列或中心格处重复写入;边界判断和循环范围要配套。
- Go 只分配外层切片不足以写入二维矩阵,还需要为每一行分配长度为
n的切片。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 54. 螺旋矩阵 | 中等 | 沿螺旋顺序移动的边界条件相同,本题写入递增数字,原题读取既有元素。 |
| 885. 螺旋矩阵 III | 中等 | 同样维护旋转方向,原题按逐步增长的步长从任意起点向外走。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!