在Python中旋转n大小的2D数组的有效方法

时间:2017-09-13 09:10:12

标签: python arrays python-3.x rotation

我想旋转(逆时针)2D nxn整数数组,2D数组存储为列表列表。

例如:

a = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]

旋转后,输出应如下所示:

b = [[3, 6, 9],
     [2, 5, 8],
     [1, 4, 7]]

我写了一个执行上述旋转的函数:

def rotate_clockwise(matrix):
    transposed_matrix = zip(*matrix) # transpose the matrix
    return list(map(list, reversed(transposed_matrix))) # reverse the transposed matrix

该功能运行良好,代码对我来说看起来很Pythonic。 但是,我无法理解我的解决方案的空间和时间复杂性。

有人可以解释我使用的构造的复杂性,即zip(*matrix)reversed(list)map(list, iterator)list(iterator)吗?

如何使此代码更高效? 另外,旋转2D矩阵的有效方法是什么?

注意:正如@Colonder在评论中所提到的,可能存在类似的问题。但是,这个问题更侧重于讨论问题的时空复杂性。

1 个答案:

答案 0 :(得分:2)

效率最高的可能就是使用numpy

>>> import numpy as np
>>> na = np.array(a)
>>> np.rot90(na)
array([[3, 6, 9],
       [2, 5, 8],
       [1, 4, 7]])

关于您当前方法的效率。如果矩阵是 n×n - 矩阵,则zip将在 O(n 2 中工作,{{1这将在 O(n)中工作(因为它以浅层方式执行),reversed函数将在 O(n)中工作,但我们这样做 n 次,因为它是在list完成的,所以map(..)将在 O(n 2 )< / em>的。最后,外部列表将再次在 O(n)中工作。但是,无法在少于 O(n 2 中轮换显式,因为我们需要移动 O(n < sup> 2 )项目。

就空间复杂度而言map(list,..)zip等以迭代方式工作。但map会强制reversed完全枚举的事实。来自zip的每个元组都需要 O(n),因此分配的内存总量将为 O(n 2 。接下来,zip再次迭代工作,每个元组将转换为一个列表,再次需要 O(n)。我们这样做 n 次。因此它会产生 O(n 2 内存复杂性。

在numpy中,如果你不在原地旋转,这将需要 O(n 2 :这是一个下限,因为新矩阵将需要 O(n 2 记忆。但是,如果你旋转 inplace ,内存的复杂性可以减少为 O(1)