题目链接:
题目描述:
解题思路:
由于是以从外圈到内圈的顺序依次打印,我们可以把矩阵想象成若干个圈,如图1所示。我们可以用一个循环来打印矩阵,每一次打印矩阵中的一个圈。
接下来分析循环结束的条件。假设这个矩阵的行数是rows,列数是columns。打印第一圈的左上角的坐标是(0,0),第二圈的左上角的坐标是(1,1),依此类推。我们注意到,左上角的坐标中行数和列数总是相同的,于是可以在矩阵中选取左上角为(start,start)的一圈作为我们分析的目标。
对于一个5*5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2,2)。我们发现5>2*2。对于一个6*6的矩阵而言,最后一圈有4个数字,其左上角的坐标仍然为(2,2)。我们发现6>2*2依然成立。于是我们可以得出结论,让循环继续的条件是columns>startX*2并且rows>startY*2。
接着我们考虑如何打印一圈的功能,如图2所示,我们可以把打印一圈分为四步:
- 从左到右打印一行。
- 从上到下打印一列。
- 从右到左打印一行。
- 从下到上打印一列。
每一步我们根据起始坐标和终止坐标用一个循环就能打印出一行或者一列。
注意,最后一圈有可能退化成只有一行、只有一列,甚至只有一个数字,因此打印这样的一圈就不再需要四步。如图2所示,是几个退化后的例子,打印一圈分别只需要三步、两步甚至一步。
因此,我们要分析打印每一步的前提条件。
- 第一步总是需要的,因为打印一圈至少有一步。如果只有一行,那么就不需要第二步了。
- 第二步的前提条件是终止行号大于起始行号。
- 第三步打印的前提条件是圈内至少有两行两列,也就是说除了要求终止行号大于起始行号外,还要求终止列号大于起始列号。
- 需要打印第四步的前提条件是至少有三行两列,因此要求终止行号比起始行号至少大2,同时终止列号大于起始列号。
已经AC的代码:
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
res = []
rows = len(matrix)
columns = len(matrix[0])
if matrix == None or rows <= 0 or columns <=0:
return
start = 0
while columns > start * 2 and rows > start *2:
endX = columns - 1 -start
endY = rows - 1 -start
# 从左到右打印一行
for i in range(start,endX+1):
res.append(matrix[start][i])
# 从上到下打印一行
if start < endY:
for i in range(start+1, endY+1):
res.append(matrix[i][endX])
# 从右到左打印一行
if start < endX and start < endY:
for i in range(endX-1, start-1, -1):
res.append(matrix[endY][i])
# 从下到上打印一列
if start < endX and start < endY - 1:
for i in range(endY-1, start, -1):
res.append(matrix[i][start])
start += 1
return res
sol = Solution()
# matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
matrix = [[1],[2],[3],[4],[5]]
print(sol.printMatrix(matrix))