1. 题目
输入一个矩阵,按照从外向里以顺时针的顺序一次打印出每一个数字。例如,如果输入如下矩阵:
- | - | - | - |
---|---|---|---|
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。
2. 解题思路
在解决这个问题是会在代码中包含多个循环,并且需要判断多个边界条件。若果吧问题考虑的很清楚之前就开始写代码,则不可避免低会越写越混乱。因此解决这个问题的关键在于先形成清晰的思路,并把复杂的问题分解称若干个简单的问题。
复杂问题一定要多画图帮助思考。
把矩阵想象成若干个圈,用一个循环来打印,每次循环打印矩阵中的一个圈。
第1圈的起点为(0, 0)
第2圈的起点为(1, 1)
第3圈的起点为(2, 2)
…
选取矩阵中左上角为(start, start)的一圈作为我们分析的目标。
对于一个5 * 5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2, 2)。我们发现5 > 2 * 2。
对于一个6 * 6的矩阵而言,最后一圈有4个数字,其左上角的坐标仍然是(2, 2)。我们发现6 > 2 * 2依然成立。于是可以得出,让循环继续的条件是columns > startX * 2并且rows > startY * 2。所以我们可以用如下的循环来打印矩阵:
打印每一圈的元素时,
- 从左到右打印一行,
- 从上到下打印一列,
- 从右到左打印一行,
- 从下到上打印一列,
- 需要注意的是最后一圈可能退化成只有一行,只有一列,只有一个数字的情况。此时打印一圈的就不要4步了。
3. 代码实现
顺时针打印矩阵
def print_matrix_clock_wisely(numbers, columns, row):
if numbers == None or columns <= 0 or rows <= 0:
return
start = 0; # 打印的起点
while columns > start * 2 and rows > start * 2:
print_matrix_in_circle(numbers, columns, rows, start)
start += 1
打印矩阵中的一圈元素
def print_matrix_in_circle(numbers, columns, rows, start):
endX = columns - 1 - start
endY = rows - 1 -start
# 从左到右打印一行
i = start
while i <= endX:
number = numbers[start][i]
print_number(number)
i += 1
# 从上到下打印一列
if start < endY:
i = start + 1
while i <= endY:
number = numbers[i][endX]
print_number(number)
i += 1
# 从右到左打印一行
if start < endX and start < endY:
i = endX -1
while i >= start:
number = numbers[endY][i]
print_number(number)
i -= 1
if start< endY and start < endY-1:
i = endY -1
while i >= start+1:
number = numbers[i][start]
print_number(number)
i -= 1
4. 总结
矩阵有点复杂,后面有时间再分析
5. 参考文献
[1] 剑指offser丛书