Stefan Pochmann 的上帝之手(2)旋轉(zhuǎn)打印矩陣

螺旋矩陣

給定一個包含 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]

普通寫法1 (18行)

鏈接:https://leetcode-cn.com/problems/spiral-matrix/solution/luo-xuan-ju-zhen-by-leetcode-solution/
模擬螺旋矩陣的路徑仿荆,初始位置是矩陣的左上角,初始方向是向右鲤桥,當路徑超出界限或者進入之前訪問過的位置時揍拆,則順時針旋轉(zhuǎn),進入下一個方向芜壁。判斷路徑是否進入之前訪問過礁凡,需要使用一個與輸入矩陣大小相同的輔助矩陣 \textit{visited}高氮,其中的每個元素表示該位置是否被訪問過慧妄。當一個元素被訪問時,將 \textit{visited} 中的對應(yīng)位置的元素設(shè)為已訪問剪芍。

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return list()
        
        rows, columns = len(matrix), len(matrix[0])
        visited = [[False] * columns for _ in range(rows)]
        total = rows * columns
        order = [0] * total

        directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        row, column = 0, 0
        directionIndex = 0
        for i in range(total):
            order[i] = matrix[row][column]
            visited[row][column] = True
            nextRow, nextColumn = row + directions[directionIndex][0], column + directions[directionIndex][1]
            if not (0 <= nextRow < rows and 0 <= nextColumn < columns and not visited[nextRow][nextColumn]):
                directionIndex = (directionIndex + 1) % 4
            row += directions[directionIndex][0]
            column += directions[directionIndex][1]
        return order

普通寫法2 (17行)

可以將矩陣看成若干層塞淹,首先輸出最外層的元素,其次輸出次外層的元素罪裹,直到輸出最內(nèi)層的元素饱普。定義矩陣的第 k 層是到最近邊界距離為 k 的所有頂點。例如状共,下圖矩陣最外層元素都是第1層套耕,次外層元素都是第2層,剩下的元素都是第3層峡继。

[[1, 1, 1, 1, 1, 1, 1],
 [1, 2, 2, 2, 2, 2, 1],
 [1, 2, 3, 3, 3, 2, 1],
 [1, 2, 2, 2, 2, 2, 1],
 [1, 1, 1, 1, 1, 1, 1]]

對于每層冯袍,從左上方開始以順時針的順序遍歷所有元素。假設(shè)當前層的左上角位于(\textit{top}, \textit{left})碾牌,右下角位于 (\textit{bottom}, \textit{right})康愤,按照如下順序遍歷當前層的元素。

  • 從左到右遍歷上側(cè)元素舶吗,依次為(\textit{top}, \textit{left})(\textit{top}, \textit{right})征冷。
  • 從上到下遍歷右側(cè)元素,依次為(\textit{top} + 1, \textit{right})(\textit{bottom}, \textit{right})誓琼。
  • 如果\textit{left} < \textit{right}\textit{top} < \textit{bottom}检激,則從右到左遍歷下側(cè)元素,依次為(\textit{bottom}, \textit{right} - 1)(\textit{bottom}, \textit{left} + 1)
  • 以及從下到上遍歷左側(cè)元素腹侣,依次為(\textit{bottom}, \textit{left})(\textit{top} + 1, \textit{left})叔收。
    遍歷完當前層的元素之后,將\textit{left}\textit{top}分別增加1筐带,將\textit{right}\textit{bottom}分別減少1今穿,進入下一層繼續(xù)遍歷,直到遍歷完所有元素為止伦籍。
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return list()
        
        rows, columns = len(matrix), len(matrix[0])
        order = list()
        left, right, top, bottom = 0, columns - 1, 0, rows - 1
        while left <= right and top <= bottom:
            for column in range(left, right + 1):
                order.append(matrix[top][column])
            for row in range(top + 1, bottom + 1):
                order.append(matrix[row][right])
            if left < right and top < bottom:
                for column in range(right - 1, left, -1):
                    order.append(matrix[bottom][column])
                for row in range(bottom, top, -1):
                    order.append(matrix[row][left])
            left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1
        return order

普通寫法3(19行)

鏈接:https://www.nowcoder.com/questionTerminal/9b4c81a02cd34f76be2659fa0d54342a?toCommentId=1128425
來源:爬渡梗客網(wǎng)
模擬魔方逆時針旋轉(zhuǎn)的方法腮出,一直做取出第一行的操作。例如 :

1 2 3
4 5 6
7 8 9

輸出并刪除第一行后芝薇,再進行一次逆時針旋轉(zhuǎn)胚嘲,就變成:

6 9
5 8
4 7

繼續(xù)重復(fù)上述操作即可。

class Solution:
    # matrix類型為二維列表洛二,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        result = []
        while(matrix):
            result+=matrix.pop(0)
            if not matrix or not matrix[0]:
                break
            matrix = self.turn(matrix)
        return result
    def turn(self,matrix):
        num_r = len(matrix)
        num_c = len(matrix[0])
        newmat = []
        for i in range(num_c):
            newmat2 = []
            for j in range(num_r):
                newmat2.append(matrix[j][i])
            newmat.append(newmat2)
        newmat.reverse()
        return newmat

上帝之手(1行)

思路與解法3一樣馋劈,每次取第一行并逆時針旋轉(zhuǎn),直到矩陣為空晾嘶。

def spiralOrder(self, matrix):
        return matrix and list(matrix.pop(0)) + self.spiralOrder(zip(*matrix)[::-1])

技巧1:zip語句將矩陣按列重組妓雾,*matrix表示元組。zip(*matrix)將從第一列開始排到最后一列垒迂,[::-1]表示倒序械姻,zip(*matrix)[::-1]表示matrix逆時針旋轉(zhuǎn)一次。例子:

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

zip(*matrix)

[(1, 4), 
 (2, 5),
 (3, 6)]

zip(*matrix)[::-1]

[(3, 6), 
 (2, 5), 
 (1, 4)]

技巧2:遞歸調(diào)用函數(shù)自身机断。這一步減少了代碼量楷拳,代價是使用堆棧,運行會變慢吏奸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末欢揖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子奋蔚,更是在濱河造成了極大的恐慌她混,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旺拉,死亡現(xiàn)場離奇詭異产上,居然都是意外死亡,警方通過查閱死者的電腦和手機蛾狗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門晋涣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沉桌,你說我怎么就攤上這事谢鹊。” “怎么了留凭?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵佃扼,是天一觀的道長。 經(jīng)常有香客問我蔼夜,道長兼耀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮瘤运,結(jié)果婚禮上窍霞,老公的妹妹穿的比我還像新娘。我一直安慰自己拯坟,他們只是感情好但金,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著郁季,像睡著了一般冷溃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梦裂,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天似枕,我揣著相機與錄音,去河邊找鬼塞琼。 笑死菠净,一個胖子當著我的面吹牛禁舷,可吹牛的內(nèi)容都是我干的彪杉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼牵咙,長吁一口氣:“原來是場噩夢啊……” “哼派近!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起洁桌,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤渴丸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后另凌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谱轨,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年吠谢,在試婚紗的時候發(fā)現(xiàn)自己被綠了土童。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡工坊,死狀恐怖献汗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情王污,我是刑警寧澤罢吃,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站昭齐,受9級特大地震影響尿招,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一就谜、第九天 我趴在偏房一處隱蔽的房頂上張望把沼。 院中可真熱鬧,春花似錦吁伺、人聲如沸饮睬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捆愁。三九已至,卻和暖如春窟却,著一層夾襖步出監(jiān)牢的瞬間昼丑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工夸赫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留菩帝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓茬腿,卻偏偏與公主長得像呼奢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子切平,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355