旋转数组(90 ∘ ^{\circ} ∘,180 ∘ ^{\circ} ∘,270 ∘ ^{\circ} ∘)
-
顺时针旋转90 ∘ ^{\circ} ∘
第一种是用坐标变换法,在网上看到的一种坐标变换:
顺时针90 ∘ ^{\circ} ∘:
newArr[i][j]=arr[N-1-j][i]
顺时针180 ∘ ^{\circ} ∘:
newArr[i][j]=arr[N-1-i][N-1-j]
顺时针270 ∘ ^{\circ} ∘:
newArr[i][j]=arr[j][N-1-i]
第二种根据特点,先观察
matrix
与转置后的matrix
与顺时针旋转90 ∘ ^{\circ} ∘。- 原矩阵
1 2 3 4 5 6 7 8 9 - 转置
1 4 7 2 5 8 3 6 9 - 旋转90 ∘ ^{\circ} ∘
7 4 1 8 5 2 9 6 3 观察可知,转置后矩阵每行反转即得到顺时针旋转90 ∘ ^{\circ} ∘的矩阵,故可用以下代码实现:
def rotate90(matrix): # 先写最简单的逐元素的转置方法 N = len(matrix) # 先转置 for i in range(N): for j in range(i,N): matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j] # 再翻转每一行 for i in range(N): matrix[i].reverse() return matrix
第三种方法,使用函数式编程的方法,其实顺时针旋转90 ∘ ^{\circ} ∘等价于先将原来的矩阵上下翻转然后再转置,逆时 针旋转90 ∘ ^{\circ} ∘等价于先将原来的矩阵转置再上下翻转。这个过程可以用表格演示一下:
1)先上下翻转再转置等价于顺时针旋转90 ∘ ^{\circ} ∘
上下翻转
7 8 9 4 5 6 1 2 3 转置
7 4 1 8 5 2 9 6 3 2) 先转置再上下翻转等价于逆时针旋转90 ∘ ^{\circ} ∘
转置
1 4 7 2 5 8 3 6 9 上下翻转
3 6 9 2 5 8 1 4 7 这个其实就是逆时针旋转90 ∘ ^{\circ} ∘。
既然前面讲了可以通过先转置再左右翻转的方法实现顺时针旋转90 ∘ ^{\circ} ∘,为什么又要讲这种方法呢?老实地说是因为我看到大神这么写,代码很简洁,就贴在这儿,加点自己的分析,23333。
好了,言归正传。
python
中矩阵是按行存储的,所以对于二维矩阵来说,实现上下翻转很简单:matrix=matrix[::-1]
,转置的话可以用zip(*matrix)
来实现。
此处补充一下,zip(*matrix)
为什么能实现转置,首先,假设matrix
的形状是n*m
的,*matrix
把matrix
矩阵分解为n
个长度为m
的列表,然后zip
依次取这些列表的各个元素构成m
个长度为n
的元组,故它可实现转置。
举个例子,matrix=[[1,2,3],[4,5,6]
,*matrix
将其变成[1,2,3],[4,5,6]
再传给zip
,zip
之后结果为(1,4),(2,5),(3,6)
。可见实现了转置。具体代码:
def rotate90(matrix): # matrix[:] = map(list,zip(*matrix[::-1])) # 这种方法是原地修改,会修改传入的矩阵 matrix = list(map(list,zip(*matrix[::-1]))) # 这种方法不是原地修改,对原来矩阵无影响 return matrix
以上代码解读:
matrix[::-1]
为将矩阵上下翻转zip(*matrix[::-1])
中,*
将翻转矩阵解压成N
个列表,然后使用zip
使这些列表变成N
个分别含有各行的第1-N
个元素的元组map(list,..)
使前面的结果重新变成列表- 以
matrix=[[1,2,3],[4,5,6],[7,8,9]]
为例 matrix[::-1]=[[7,8,9],[4,5,6],[1,2,3]]
zip(*matrix[::-1])
将matrix[::-1]
先解成三个列表[7,8,9],[4,5,6],[1,2,3]
,然后对这三个列表使用zip
,生成一个zip
对象,里面是三个元组(7,4,1),(8,5,2),(9,6,3)
map(list,...)
将上述三个元组变为列表,再通过list
方法把它们由map
对象变成列表- 因此
matrix = list(map(list,zip(*matrix[::-1])))
得到的是顺时针旋转90 ∘ ^{\circ} ∘后的矩阵
至于顺时针旋转180 ∘ ^{\circ} ∘,其实就是先上下翻转,再左右翻转;而顺时针旋转270 ∘ ^{\circ} ∘即为逆时针旋转90 ∘ ^{\circ} ∘,它们的代码分别贴下:
def rotate180(matrix): N = len(matrix) matrix = matrix[::-1] for i in range(N): matrix[i] = list(reversed(matrix[i])) # 这一步不用matrix[i].reverse()是为了防止对原数组的各行进行翻转 return matrix def rotate270(matrix): matrix = list(map(list,zip(*matrix)))[::-1] return matrix