Leetcode算法——54、螺旋矩阵(spiral matrix)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HappyRocking/article/details/84938127

给定一个矩阵 m*n,返回所有元素的螺旋排列顺序(从左上角开始,顺时针旋转,由外向内)。

示例1:

Input:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]

示例2:

Input:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]

思路

1、递归法

先输出最外圈的顺时针顺序,然后用同样方法处理剩下的元素。

最外圈的顺时针顺序为:
1、最上面一行,从左到右
2、最右面一列,从上到下
3、最下面一行,从右到左
4、最左面一列,从下到上

然后,使用递归法,处理第二圈、第三圈等,直到矩阵最中间的一圈被处理完毕(这也是递归结束条件)。

2、递归法(一行代码)

另外一种递归法:
1、读取最上面一行,从左到右
2、将最上面一行从矩阵中删除
3、将矩阵逆时针旋转90度。
4、递归,继续处理最上面一行。

递归结束条件:矩阵为空。

实际上,这种方法只需要用一行python代码便可以实现:

def spiralOrder2(matrix):
    return matrix and [*matrix.pop(0)] + spiralOrder2([*zip(*matrix)][::-1])

其中,

1、当 matrix = [] 时,matrix and [*matrix.pop(0)] 这个表达式返回 [],这是因为 and 符号连接时,先计算左边的正负,时,matrix 为空,为FALSE,因此不必再计算 and 右边的表达式。直接返回 matrix,即 []。

2、[*zip(*matrix)] 表示将 matrix 的第一列作为第一行,第二列作为第二行… 即将矩阵进行对角线对称。

python语法:

* 后面加上可迭代对象,相当于将可迭代对象依次列出

可以用在两个场合:
1、[*a] 表示将a变为list,相当于 list(a)
2、fun(*a) 表示将a变为list,并且每个元素分别作为fun()的一个参数,即这时 fun 被传入了多个参数,而不是一个。
比如:

    >>> matrix = [1,2,3]
    >>> type(*matrix)
    Traceback (most recent call last):
        File "<ipython-input-283-d63d2bd0f73e>", line 1, in <module>
            type(*matrix)
    TypeError: type.__new__() argument 1 must be str, not int

相当于执行了 type(1,2,3),因此会报错。

3、[*zip(*matrix)][::-1] 表示先将 matrix 进行对角线对称,然后将所有行逆序排列。

比如原矩阵为:

matrix = [
[1,2,3],
[4,5,6]
]

先对角线对称:

matrix2 = [
[1,4],
[2,5],
[3,6]
]

再逆序排列:

matrix3 = [
[3,6],
[2,5]
[1,4]
]

可见, matrix3 是 matrix 逆时针旋转 90 度的结果。

python实现

def spiralOrder(matrix):
    """
    :type matrix: List[List[int]]
    :rtype: List[int]
    递归法。
    先输出最外圈的顺时针顺序,然后用同样方法处理剩下的元素。
    """
    
    # 递归结束条件
    if not matrix or len(matrix[0]) == 0:
        return []
    if len(matrix) == 1: # 只有一行
        return matrix[0]
    if len(matrix[0]) == 1: # 只有一列
        return [x[0] for x in matrix]
    
    # 最外圈的螺旋排列
    result = matrix[0] # 第一行
    result += [x[-1] for x in matrix][1:-1] # 最后一列
    result +=  matrix[-1][::-1] # 最后一行
    result += [x[0] for x in matrix][-2:0:-1]  # 第一列
    
    # 切割出剩余元素
    remain = [matrix[i][1:-1] for i in range(1,len(matrix)-1)]
    
    return result + spiralOrder(remain)

def spiralOrder2(matrix):
    '''
    递归法,一行代码。
    '''
    return matrix and [*matrix.pop(0)] + spiralOrder2([*zip(*matrix)][::-1])

if '__main__' == __name__:
    matrix = [
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
    print(spiralOrder2(matrix))

猜你喜欢

转载自blog.csdn.net/HappyRocking/article/details/84938127