所谓顺时针转圈打印数字,即从外往内打印数组,一圈一圈地打印,这是剑指offer的第20题。
这个题的思路是这样的:
首先,打印的条件是
rows>2*start and cols>2*start
,然后把打印一圈分为四步
- 首先从左到右打印一行,这一步是任意情况都要执行的,即使只有
1
行1
列;- 然后从上到下打印一列,这一步的条件是至少有两行;
- 再执行从右到左打印一行,这一步的条件是至少有两行两列,因为若只有两行一列,那么在第2步就打印完成了;
- 最后执行从下到上打印一列,这一步的条件是至少有三行两列。
现在问题转化为如何具体化上述每一步的执行条件和打印的范围,首先需要明确的是打印的起始坐标是横纵相等的,设其为
start
,则横方向上打印的最大坐标为endX = cols - 1 - start
,列方向上打印的最大坐标为endY = rows - 1 - start
,现在确定每一步的条件和打印范围。
- 无条件,打印坐标为
matrix[start][i]
,i
的范围为[start,endX]
;- 条件为:
endY>start
,打印坐标为matrix[i][endX]
,i
的范围为[start+1,endY]
;- 条件为:
endY>start and endX>start
,打印坐标为matrix[endY][i]
,i
的范围为[endX-1,start]
;(注意这里是反向的)- 条件为:
endY>start+1 and endX>start
,打印坐标为matrix[i][start]
,i
的范围为[endY-1,start+1]
;(注意这里是反向的)
即打印方式为:
代码:
def printMatrix(matrix):
rows = len(matrix)
if rows<1:
print('[]')
cols = len(matrix[0])
start = 0
while rows > 2 * start and cols > 2 * start:
endX = cols - 1 - start
endY = rows - 1 - start
# 第一步,从左到右打印一行
for i in range(start,endX+1):
print(matrix[start][i])
# 第二步,从上到下打印一列
# 要求至少有两行
if endY > start:
for i in range(start+1,endY+1):
print(matrix[i][endX])
# 第三步,从右到左打印一行
# 要求至少有两行两列
if endY > start and endX > start:
for i in reversed(range(start,endX)):
print(matrix[endY][i])
# 第四步,从下到上打印一列
# 要求至少有三行两列
if endY > start + 1 and endX > start:
for i in reversed(range(start+1,endY)):
print(matrix[i][start])
start += 1