题目描述
回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。
输入描述
输入第一行是两个不超过 200 的正整数 m,n,表示矩阵的行和列。接下来 m 行每行 n 个整数,表示这个矩阵。
输出描述
输出只有一行,共 mn 个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。
输入输出样例
示例
输入
3 3
1 2 3
4 5 6
7 8 9
输出
1 4 7 8 9 6 3 2 5
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
代码
dir = [(1, 0), (0, 1), (-1, 0), (0, -1)] #4个方向
m, n = map(int, input().split())
a = []
for i in range(m):
a.append(input().split())
x, y = -1, 0
d = 0
sum = 0
while sum < m*n:
sum = sum + 1 #此处计数
nx, ny = x + dir[d][0], y + dir[d][1] #按此方向遍历
if nx < 0 or nx >= m or ny < 0 or ny >= n or a[nx][ny]==-1: #检查是否到边界或者是否遍历完成
d = (d + 1) % 4 #dir中总共只有四个方向
x, y = x + dir[d][0], y + dir[d][1]
else:
x, y = nx, ny
print(a[x][y], end=' ')
a[x][y] = -1 #标记这个坐标点已经取过
解析
获取数据
这一题解法很巧妙
第一行用一个列表定义了四个元组,每个元组中存储的都是每次遍历数组的x(代表行数),y(代表列数)要增加的值,如向下方向遍历,那么选择第一个元组,每次x加1,y不变即可。
第二行使用了map将输入的数据转换为列表赋值给x,y,如输入:
3 3
首先input().split()默认使用空格换行符来拆分接受的输入,返回一个参数列表,相当于:
m,n=map(int,['3','3'])
map()将此列表中的每一个元素做int处理,即转换为整型,返回一个列表迭代器,相当于:
m, n = [3, 3]
用列表对变量赋值,得到m=3,n=3
第四行用来接收这个二维数组,因为总共有m行个整数,因此迭代m次(0到m-1,共m个),存入m个列表,每个列表的长度是用户输入的数据的长度。
该代码将用户输入的一行字符串切片,转换为一个列表
input().split()
将该列表添加到a列表,因此实际上a是一个二维列表:
a.append(input().split())
如输入的第一行数据为:
1 2 3
那么首先切片,转换为一个列表:
['1','2','3']
再将该列表添加到a列表,此时的a列表的值为:
a=[['1','2','3'],]
以上就获得了全部的数据。
处理数据
第九行是一个循环条件,每循环一个给sum加一,当遍历完所有数sum=m*n时停止循环
这里用变量d来选择遍历所用的方向,因为首先向下,所以d=0,选择第一个元组,每次遍历x的值加1,y的值不变,即行加一,列不变。
第11行,nx,ny用来计算在这次遍历中x,y的坐标改变后的值,用于接下来访问该位置的元素
第十二行判断是否到了边界(当访问到有-1的元素时,意味着该元素已经遍历,需要改变方向),如果到了边界要更改访问的列表的方式,这里使用:
d = ( d + 1 ) % 4
来循环地使d取0,1,2,3改变选择的方向元组,改变每次遍历的x,y增加值
在访问过该元素后,将这个位置的元素值置1
最后当sum=m*n时,意味着所有元素已经遍历完成,循环结束。
总结
这一题要求沿矩形边界取数改变方向,因为方向总共只有四种(上,下,左,右),因此用一个列表来存储每一个方向对x,y的操作,当访问数据遇到边界时,按顺序来改变方向即可。