54:旋转矩阵

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了。

转载于:https://www.cnblogs.com/tbgatgb/p/11197842.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值