54. 螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]
Python most votes solution:
class Solution(object):
def spiralOrder(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: List[int]
"""
print([*zip(*matrix)][::-1])
return matrix and [*matrix.pop(0)] + self.spiralOrder([*zip(*matrix)][::-1])
注意:以上代码必须在python 3.x版本下运行。
分析:
大体思路是每次将矩阵的第一行剔除掉,然后将剩余的部分顺时针旋转90°,得到一个新矩阵;
再将新矩阵的第一行剔除出来,然后将剩余的部分顺时针旋转90°,又得到一个新矩阵;
......
如此重复进行,直到将矩阵剔空。
具体过程详见:https://leetcode.com/problems/spiral-matrix/discuss/20571/1-liner-in-Python-%2B-Ruby
以下对这里边存在的一些问题进行说明:
(1)当return语句中含有and时python是如何处理的?
答:见:https://www.cnblogs.com/zealousness/p/8749152.html
该代码正是借助这一点来保证当矩阵被剔空时,算法能够继续地停止,而不是无限制地递归下去。
(2)[*matrix.pop(0)]
中[*]
的含义?
答:因为后面代码中的zip函数将矩阵转换成了tuple,而最终要返回的结果是list,所以这里的中括号是为了将将pop出来的内容放到一个list里面;
然后,为什么会有一个 * 号?这是因为pop出来的对象是tuple,这里用一个 * 号,配合中括号使用,可以将该tuple转换成一个list(而且是一维的list,等价于直接把tuple的括号去掉了),从而为结果输出list做准备。
(3)如何将一个矩阵顺时针旋转90°?
答:设A为一个矩阵,则以下操作可以将该矩阵顺时针旋转90°:
zip(*A)[::-1]
关于zip函数的用法详见:
Python 2 中zip函数的用法:https://www.runoob.com/python/python-func-zip.html
Python 3 中zip函数的用法:https://www.runoob.com/python3/python3-func-zip.html
但是在Python 3 中,这样顺时针旋转后得到的是一个zip对象,而不是一个矩阵。如何使旋转后仍然得到一个矩阵呢?详见下面一个问题。
(4)[*zip(*matrix)][::-1]
中[*]
的含义?
答:上一个问题谈到,旋转后将得到一个zip对象而非矩阵,这里的 * 是一个针对zip的解压操作,它可以对一个zip对象进行解压,但是解压后返回的对象是tuple类型,这里的中括号是为了将解压后的对象封装成list(但是list中的元素仍是tuple)。这样做的目的是为了保证在递归时,每一次传递给下一次的参数均是list,从而和第一次传入spiralOrder函数的参数类型保持一致。
关于zip()和*zip()的区别详见:https://www.cnblogs.com/waltsmith/p/8029539.html
(5)程序是如何做到每次将矩阵的第一行剔除出来,然后仅让剩余的矩阵参与旋转的?
答:这里的剔除操作是通过pop(0)实现的,这里需要注意的是,这一pop操作是会改变矩阵matrix本身的,pop后再引用matrix时,这个matrix就已经是少了第一行后的matrix了。