输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
限制:
- 0 <= matrix.length <= 100
- 0 <= matrix[i].length <= 100
根据题目的描述可知,这里需要完成的就是顺时针打印矩阵元素的问题。抛开具体的实现不谈,如果要顺时针的打印一个矩阵,示意图如下所示:
整个打印元素的过程就是访问矩阵元素的过程,根据上图可知,需要如下的辅助设置帮助解题:
方向的控制,directions
:访问过程所涉及的方向一共有四种:
布尔类型访问矩阵,vis
:用于判断当前元素是否被访问过,如果已被访问过,值为True;否则为False
对于矩阵中某一个位置来说,可以使用[row, col]
的坐标形式表示:
[row + 0, col + 1]
,直到遇到边界位置;[row -1, col + 0]
,直到遇到边界位置;[row + 0, col - 1]
,直到遇到边界位置;[row - 1, col + 0]
, 直到遇到边界位置;因此,可以使用[0, 1]
、[1, 0]
、[0, -1]
[-1, 0]
来执行上述的四个操作。依次访问矩阵元素:
vis[row][col] = True
,然后计算下一个访问位置的row
和col
的值0 <= row < rows, 0 <= col < cols
,并且下一个位置没有被访问过vis[row][col] == False
row
和col
的值,继续访问class Solution:
def spiralOrder(self, matrix):
if not matrix: return []
rows, cols = len(matrix), len(matrix[0])
vis = [[False] * cols for _ in range(rows)]
order = []
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
row, col, flag = 0, 0, 0
for i in range(rows * cols):
order.append(matrix[row][col])
vis[row][col] = True
nextRow, nextCol = row + directions[flag][0], col + directions[flag][1]
if not (0 <= nextRow < rows and 0 <= nextCol < cols and not vis[nextRow][nextCol]):
flag = (flag + 1) % 4
row, col = row + directions[flag][0], col + directions[flag][1]
return order
另外一种访问方式就是按圈访问,如下所示:
这种访问方式最重要的就是访问边界的控制,同样是按照➡⬇⬅⬆的访问。我们可以使用4个while循环来控制访问的过程,只要每一次访问没有达到相应的边界,那么就持续访问。一圈访问结束后,进行下一圈的访问,直到访问完最后一圈,对于终止条件的判断,我们可以通过改变每一圈左上角和右下角的坐标表示,假设左上角为[lr, lc]
,右下角为[rr, rc]
,那么访问完一圈后,相应的坐标改变为[lr + 1, lc + 1]
和[rr - 1, rc - 1]
。如果lr == rr and lc == rc
,则访问结束。
另外,当访问到最里面一圈时,此时可能只有一行或是一列(取决于矩阵的行列数值大小)。因此,访问逻辑中需要对单行和单列做额外的访问控制。
class Solution:
def spiralOrder(self, matrix):
r = []
def visit(matrix, lr, lc, rr, rc):
# 如果只有一行
if lr == rr:
for i in range(lc, rc + 1):
r.append(matrix[lr][i])
# 如果只有一列
elif lc == rc:
for i in range(lr, rr + 1):
r.append(matrix[i][lc])
else:
curR, curC= lr, lc
while curC < rc:
r.append(matrix[lr][curC]) # 向右访问
curC += 1
while curR < rr:
r.append(matrix[curR][rc]) # 向下访问
curR += 1
while curC > lc:
r.append(matrix[rr][curC]) # 向左访问
curC -= 1
while curR > lr:
r.append(matrix[curR][lc]) # 向上访问
curR -= 1
if not matrix: return []
rows, cols = len(matrix), len(matrix[0])
# 左上角
lr, lc = 0, 0
# 右下角
rr, rc = rows - 1, cols - 1
while lr <= rr and lc <= rc:
visit(matrix, lr, lc, rr, rc)
lr, lc = lr + 1, lc + 1
rr, rc = rr -1, rc - 1
return r