题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
思路:螺旋访问数组是常见的一类题目,还可以变形为螺旋生成n维数组。这类题目思路都是相同的,主要是控制访问每行每列的边界。
考虑:用两个变量xnum,ynum分别对访问列方向、行方向上前进步数的限制。ynum初始值为列数, xnum初始值为行数-1。打印具体过程如下:
当行列方向可前进步数均不为0并且输出列表长度小于原矩阵元素个数时,循环以下四个方向:
→:行方向的打印,坐标y值步进,可前进步数为yum。
↓:列方向的打印,坐标x值步进,可前进步数为xnum。
走过半圈之后,ynum和xnum都减1,这是很显然的。
←:行方向的打印,坐标y值后退,为了保证与→ 方向数据不重合,需要加上xnum>=0的判断,这个判断的意思是上边界与下边界之间有间隔,因为如果此时只剩一行数据,那么意味着列方向可前进步数为0,即上一步的xnum = 0 - 1 = -1
↑:行方向的打印,坐标x值后退,为了保证与↓ 方向数据不重合,需要加上ynum>=0的判断,这个判断的意思是左边界与右边界之间有间隔,同上
def printMatrix(self, matrix):
# write code here
out = []
# m, n分别表示行、列数
m = len(matrix)
if m == 0:
return out
n = len(matrix[0])
# x,y表示当前访问到第x行第y列
x = 0
y = -1
# xnum, ynum限制当前访问方向上的元素个数
ynum = n
xnum = m - 1
while len(out) < m * n and ynum >= 0 and xnum >= 0:
for i in range(ynum):
y += 1
out.append(matrix[x][y])
for i in range(xnum):
x += 1
out.append(matrix[x][y])
ynum -= 1
xnum -= 1
if xnum >= 0:
for i in range(ynum):
y -= 1
out.append(matrix[x][y])
ynum -= 1
if ynum >= 0:
for i in range(xnum):
x -= 1
out.append(matrix[x][y])
xnum -= 1
return out
还有几种不同的思路,比如计算需要循环的圈数,按照圈数控制行列的边界,但是原理上还是相同的,这里不再进行实现。
其实使用python语言,还有更为简便的方式,不需要小心的计算每行每列元素剩余个数,也不需要计算圈数,但是缺点是改变了原矩阵。
实现代码如下,原理利用了python数组本身的性质。需要注意的是对于上下边界只需要判断原数组是否为空即可, 但是左右边界需要判断数组中是否存在空数组
def printMatrix(self, matrix):
out = []
while matrix:
# 上边界即为数组的第一个子数组
out += matrix.pop(0)
# 如果这里仅判断if matrix,那么对于测试数组例[[1],[2],[3]],循环后变成了[[],[]],matrix不为空
if matrix and matrix[0]:
# 右边界即为数组每一项的最后一个元素
for row in matrix:
out.append(row.pop())
# 下边界即为数组最后一个子数组的逆序排列
if matrix:
out += matrix.pop()[::-1]
if matrix and matrix[0]:
# 左边界即为数组从尾到头的每一项子数组的第一个元素
for row in matrix[::-1]:
out.append(row.pop(0))
return out