BM98 螺旋矩阵¶
简单通过率 27.65%python3核心代码模式样例通过牛客 AC数组
讲解章节:模拟
一句话
用上下左右四条边界圈住未访问区域,走一圈收一圈。
解题思路¶
这题考什么¶
模拟题的状态设计。与其在矩阵里模拟「撞墙就转向」(那需要一个 visited 数组 或方向表来判断何时转弯),不如直接维护四条边界 top / bottom / left / right,让它们框住「还没输出的那块矩形」。 每一圈按固定顺序走四条边,走完一条就把对应的边界往里收一格:
沿 top 行从 left 到 right(向右) 走完 top += 1
沿 right 列从 top 到 bottom(向下) 走完 right -= 1
沿 bottom 行从 right 到 left(向左) 走完 bottom -= 1
沿 left 列从 bottom 到 top(向上) 走完 left += 1
四条边界一收,剩下的仍是一块矩形,于是同一段逻辑可以直接套用到下一圈, 循环条件就是这块矩形还非空:top <= bottom and left <= right。 转向不再需要判断,顺序是写死的;visited 数组也省掉了。
走 3x3 的示例:
1 2 3 向右 1 2 3 top=1
4 5 6 向下 6 9 right=1
7 8 9 向左 8 7 bottom=1
向上 4 left=1
剩下正中一格,下一圈 top=bottom=left=right=1,向右输出 5
结果 [1,2,3,6,9,8,7,4,5]
数据规模与复杂度¶
0 <= n, m <= 10,元素绝对值 <= 100,时限「其他语言 2 秒」, 题面要求时间 O(nm)、空间 O(nm)。 每个元素恰好被输出一次,时间 O(nm);除了结果列表没有任何额外标记, 空间 O(nm) 全花在返回值上。规模极小,这题考的完全是边界处理的严谨度。
坑在哪¶
- 关键陷阱在后两条边。走完前两条边之后,四条边界可能已经交错, 此时若不加判断就往回走,会把同一行或同一列重复输出。 所以第三步之前要检查 top <= bottom,第四步之前要检查 left <= right。
- 单行矩阵 [[1,2,3]] 就是第三步的反例:向右输出 1,2,3 后 top 变成 1, 已经大于 bottom = 0;向下那一步的 range 为空没有影响, 但向左那一步若不拦,会沿着同一行倒着补出 2,1 (right 此时已经收成 1,所以多出来的是两个而不是三个)。
- 单列矩阵 [[1],[2],[3]] 是第四步的反例:向右输出 1、向下输出 2,3 之后 right 收成 -1,向左那一步的 range 为空, 但向上那一步若不拦,会再输出一次 2。
- 三个向内的循环各有一处下标细节:向右与向下的 range 右端要写成 right + 1、bottom + 1(Python 的 range 右端开区间,少加 1 就会漏掉最后一格); 向左与向上是倒序,range 的终点要写成 left - 1、top - 1, 步长 -1,同样是为了让端点被取到。
- matrix 为 [](样例 2)或 [[]] 时直接返回空列表, 否则 len(matrix[0]) 会在空矩阵上越界。
参考实现¶
[:octicons-arrow-left-16: BM97](BM97.md) [BM99 :octicons-arrow-right-16:](BM99.md)