給定一個(gè)包含 m x n 個(gè)元素的矩陣(m 行, n 列),請(qǐng)按照順時(shí)針螺旋順序,返回矩陣中的所有元素。
示例 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]
- show the code:
##code1
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix:
return matrix
res = []
while matrix:
res.extend(matrix.pop(0))
matrix = list(zip(*matrix))[::-1]
return res
#code2一行解決
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
return matrix and [*matrix.pop(0)] + self.spiralOrder([*zip(*matrix)][::-1])
- 看到上面的代碼一,關(guān)鍵思路是要找出規(guī)律:即每次循環(huán)矩陣
pop(0)第一行,而如何保證我們的第一行的順序是原矩陣順時(shí)針打印的順序呢,關(guān)鍵還是在這個(gè)zip函數(shù),有關(guān)zip函數(shù)我在之前的博客中講過了:最長(zhǎng)公共前綴(easy) - 每次刪除掉第一行后,我們使用
zip(*matrix)解壓并且用[::-1]實(shí)現(xiàn)反轉(zhuǎn),即可將下個(gè)順序放置在新矩陣的第一行,這樣每次只需要加上第一行的元素即可,注意這里要使用extend(). - 關(guān)于代碼二,一般人想不到這么簡(jiǎn)潔的代碼的,這里使用了遞歸,但其實(shí)本質(zhì)上思想與代碼一大同小異。
- 關(guān)鍵就在于一些關(guān)于的python的冷知識(shí),比如
list之間的布爾運(yùn)算and:
and如果都是真,返回最后一個(gè)值,如果有一個(gè)為假,則返回假;or返回第一個(gè)不是假的值。
有關(guān)例子:
[1,2,3] and [1]
Out[106]: [1]
[1] and [1,2,3]
Out[107]: [1, 2, 3]
[] and [1,2,3]
Out[108]: []
[] or [1]
Out[109]: [1]
[1] or [2] or []
Out[110]: [1]
[] or [] or [1]
Out[111]: [1]
- 比如對(duì)列表的加
*號(hào)處理:[*matrix.pop(0)]和[*zip(*matrix)],在python中,對(duì)list、tuple、dict前面加*號(hào)代表將其拆開,以空格為間隔。
a=[1,2,3]
b=(1,2,3)
c={1:"a",2:"b",3:"c"}
print(a,"====",*a)
print(b,"====",*b)
print(c,"====",*c)
運(yùn)行結(jié)果為:
[1, 2, 3] ==== 1 2 3
(1, 2, 3) ==== 1 2 3
{1: 'a', 2: 'b', 3: 'c'} ==== 1 2 3
序列+*相當(dāng)于解壓,與zip的功能相反
其次有時(shí)在傳入函數(shù)參數(shù)時(shí)有用,參數(shù)需要兩個(gè)而你只有一個(gè)列表時(shí),可以用*將列表拆成兩個(gè)數(shù)獨(dú)立傳入函數(shù):
def add(a, b):
return a+b
data = [4,3]
print add(*data)
#equals to print add(4, 3)
- 在代碼二中加
*之后如果不加上[]則會(huì)出現(xiàn)無限遞歸的情況,這是我修改之后嘗試跑一下試出來的,具體原因還不是很懂,保留一下疑問,希望有大神能留言解答。