【问题标题】:Efficient way to rotate a 2D array of integers of n size in Python在Python中旋转n大小整数的二维数组的有效方法
【发布时间】:2018-02-21 22:04:16
【问题描述】:

我想旋转(逆时针)一个 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)

我怎样才能让这段代码更有效率? 另外,旋转二维矩阵有效的方法是什么?

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

【问题讨论】:

  • @Colonder 我已经阅读了那个帖子,没有提到效率或关于复杂性的讨论。
  • 如果您可以使用 numpy,我相信 numpy.rot90 可以满足您的需求。
  • @AaronN.Brock 不,即使我愿意,我也不能!我只能使用标准库功能。

标签: python arrays python-3.x rotation


【解决方案1】:

最有效的可能是为此使用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(n2)reversed 将在这里在 O(n) 中工作(因为它以浅层的方式执行此操作),list 函数将在 O(n) 中工作,但我们这样做 n 次,因为它是在 map(..) 中完成的,所以 map(list,..) 将在 O(n2) 中工作。最后,外部列表将在 O(n) 中再次起作用。然而,没有办法在 O(n2) 内旋转显式,因为我们需要移动 O(n2) 个项目。

在空间复杂度方面zipmap等以迭代的方式工作。但是reversed 将强制zip 将被完全枚举。 zip 中的每个元组都需要 O(n),因此分配的内存总量将是 O(n2)。接下来,map(list,..) 再次迭代工作,每个元组将被转换为一个列表,这又需要 O(n)。我们这样做 n 次。所以会产生O(n2)的内存复杂度。

在 numpy 中,如果您不就地旋转,这也需要 O(n2):这是一个下限,因为新矩阵需要O(n2) 个内存。但是,如果您进行 inplace 旋转,则内存复杂度可以降低到 O(1)

【讨论】:

  • 您能否也解决空间复杂度问题?
  • 我们可以在不使用numpy的情况下就地执行旋转吗?
  • 为了结束,您能在这里添加吗? :)
猜你喜欢
  • 1970-01-01
  • 2018-01-06
  • 2021-11-02
  • 2015-07-19
  • 1970-01-01
  • 2011-03-29
  • 2011-02-08
  • 2017-01-05
相关资源
最近更新 更多