【矩阵专题】Leetcode54.螺旋矩阵
螺旋矩阵
一、题目描述
给你一个 m x n
的矩阵 matrix
,请按照螺旋顺序返回矩阵中的所有元素。
示例:
输入:
matrix = [[1, 2, 3],[4, 5, 6],[7, 8, 9]
]
输出:
[1, 2, 3, 6, 9, 8, 7, 4, 5]
二、解题思路:模拟“画圈圈”的过程
这道题最直接的做法是模拟“从外到内逐层遍历”的过程,也就是四个方向依次遍历:
- 从左到右遍历顶部行
- 从上到下遍历右侧列
- 从右到左遍历底部行
- 从下到上遍历左侧列
然后不断地收缩边界,直到遍历完整个矩阵。
三、图解说明
如下图所示(以 3x3 矩阵为例):
[ 1 → 2 → 3 ]
[ ↓ ↓ ]
[ 4 6 ]
[ ↓ ↑ ]
[ 7 ← 8 ← 9 ]
我们用四个变量控制边界:
left
:左边界right
:右边界top
:上边界bottom
:下边界
每遍历完一圈,就收缩对应边界,直到 left > right
或 top > bottom
。
四、Java 代码实现
class Solution {public List<Integer> spiralOrder(int[][] matrix) {int left = 0;int right = matrix[0].length - 1;int top = 0;int bottom = matrix.length - 1;List<Integer> ans = new ArrayList<>();while (left <= right && top <= bottom) {// 从左到右for (int i = left; i <= right; i++) {ans.add(matrix[top][i]);}top++; // 上边界下移// 从上到下for (int i = top; i <= bottom; i++) {ans.add(matrix[i][right]);}right--; // 右边界左移// 从右到左(确保当前还有未遍历的行)if (top <= bottom) {for (int i = right; i >= left; i--) {ans.add(matrix[bottom][i]);}bottom--; // 下边界上移}// 从下到上(确保当前还有未遍历的列)if (left <= right) {for (int i = bottom; i >= top; i--) {ans.add(matrix[i][left]);}left++; // 左边界右移}}return ans;}
}
五、特别说明:两个 if
判断的作用
这两个判断是避免重复遍历或越界的关键。
if (top <= bottom)
的作用:
在执行“从右向左遍历”前,需要确保还有剩余的未访问行。
比如只有一行时,从左到右遍历后,top++
,就可能已经超过 bottom
,这时就不能再从右往左遍历了。
if (left <= right)
的作用:
在执行“从下向上遍历”前,需要确保还有剩余的未访问列。
同理,如果只剩下一列,执行完“从上到下”后,right--
可能已经小于 left
,就不能再从下向上了。
六、复杂度分析
- 时间复杂度:
O(m * n)
每个元素都被访问一次。 - 空间复杂度:
O(1)
(不计输出结果所占空间)