python矩阵旋转函数_Python3算法之十:矩阵旋转
關(guān)注微信公眾號“酸痛魚”,獲得更多最新最全的文章。
本文中所涉及的代碼,在未特殊聲明的情況下,都是基于Python3程序設(shè)計語言編寫的。
建議您在PC瀏覽器中閱讀本文,以獲得更好的閱讀體驗。
0
問題描述
實現(xiàn)一個函數(shù),該函數(shù)接收一個n×n二維矩陣matrix,將該矩陣順時針旋轉(zhuǎn)90度。要求直接對參數(shù)matrix進行修改,函數(shù)不返回任務(wù)東西。
例如:
給定 matrix =
[
[1, 2],
[3, 4],
]
旋轉(zhuǎn)后為matrix=
[
[4, 1],
[3, 2],
]
給定matrix=
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
旋轉(zhuǎn)后matrix=
[
[7, 4, 1],
[8, 5, 2],
[9, 6, 3],
]
在力扣上可以找到相同的題目,叫《旋轉(zhuǎn)圖像》,其官方題解中,給出了本文中最后一種(第四種)解法的兩種實現(xiàn)方式,感興趣的讀者可以去了解一下。
本文中討論到坐標(biāo)時,都是以Python語法為參照的,即坐標(biāo)是從0開始算的。由于旋轉(zhuǎn)操作涉及到移動每一個元素,所以本題目的所有解法的時間復(fù)雜度都是O(N^2),也就是至少遍歷一次matrix。
對于矩陣的一次置換操作,如果連續(xù)做兩遍,矩陣又回到了原來的樣子,我們稱這個置換是可逆的;否則,我們稱這個置換是不可逆的。
1
公式法
對矩陣進行順時針90度旋轉(zhuǎn),相當(dāng)于把每個坐標(biāo)(r, c)的元素移動到(tr, tc)上,這兩個坐標(biāo)滿足如下的轉(zhuǎn)轉(zhuǎn)換關(guān)系:
tr = c
tc = n- r - 1
需要注意的是,上面的轉(zhuǎn)換操作是不可逆的,比如A→B, B→C,A和C是不同的元素。當(dāng)我們把A移動到B的時候,B的值被改成了A的值。所以我們必須先記錄B的值,再做B→C的操作。同樣,做B→C時,必須先記錄C的值。實際上,我們并沒有辦法動態(tài)記錄這些信息,所以我們只能先拷貝一份matrix,然后借助這份拷貝來直接對matrix進行操作。所以,這種解法遍歷了兩次matrix,拷貝一次,轉(zhuǎn)換一次;而空間復(fù)雜度則為O(N^2)。
def rotate(matrix):
n = len(matrix)
# 復(fù)制matrix
copy = [[matrix[r][c] for c in range(n)] for r in range(n)]
# 轉(zhuǎn)換公式:源坐標(biāo)(r, c),目標(biāo)坐標(biāo)(tr, tc)
# tr = c, tc = n-r-1
for r in range(n):
for c in range(n):
tr = c
tc = n - r - 1
matrix[tr][tc] = copy[r][c]
2
二次置換法
將矩陣順時針旋轉(zhuǎn)90度,可以通過二次置換得到:先將矩陣倒置,再將倒置后的矩陣的每一個行的元素順序倒置。
因為這兩種置換操作都是可逆的,所以通過這個方式,空間復(fù)雜為O(1);而這種方式也是遍歷兩次matrix,遍歷次數(shù)與第一種解法的一樣。
def rotate(matrix):
n = len(matrix)
# 矩陣倒置,即(r,c)->(c,r)
for r in range(n):
for c in range(r, n):
matrix[r][c], matrix[c][r] = matrix[c][r], matrix[r][c]
# 每一行倒轉(zhuǎn)
for r in range(n):
# 以下兩行相當(dāng)于:matrix[r] = matrix[r][::-1]
# 本著不修改matrix內(nèi)部結(jié)構(gòu)的原則,用下面的方式
for c in range(n // 2):
matrix[r][c], matrix[r][n - 1 - c] = matrix[r][n - 1 - c], matrix[r][c]
3
邊整體旋轉(zhuǎn)法
對于行列數(shù)都為n的矩陣,它總共有ceil(n / 2)圈(ceil表示向上取整)。我們可以通過對每一圈的四條邊進行順時針旋轉(zhuǎn)來實現(xiàn)總體的效果。在邊旋轉(zhuǎn)過程中,我們需要先臨時記錄其中一條邊的值,以便在最后將其放到目標(biāo)的位置。所以邊旋轉(zhuǎn)法的空間空間復(fù)雜度為O(N),而且只對matrix遍歷了一次。
每條邊從起始位置旋轉(zhuǎn)到目標(biāo)位置的坐標(biāo)轉(zhuǎn)換公式,各位讀者請自行推導(dǎo),本文將不對此進行詳細(xì)解說。
def rotate(matrix):
n = len(matrix)
mi = n - 1 # 最大索引
# 每一圈loop,對四條邊單獨旋轉(zhuǎn)
for loop in range(n // 2):
# 每一圈邊長
length = mi - 2 * loop
# 將左邊存儲到臨時變量left中
left_c = loop
left_r_start = loop
left = [matrix[left_r_start + i][left_c] for i in range(length)]
# 將底邊存到左邊
bottom_c_start = loop
bottom_r = mi - loop
for i in range(length):
matrix[left_r_start + i][left_c] = matrix[bottom_r][bottom_c_start + i]
# 將右邊存到底邊
right_c = mi - loop
right_r_start = mi - loop
for i in range(length):
matrix[bottom_r][bottom_c_start + i] = matrix[right_r_start - i][right_c]
# 將上邊存到右邊
top_r = loop
top_c_start = mi - loop
for i in range(length):
matrix[right_r_start - i][right_c] = matrix[top_r][top_c_start - i]
# 將左邊,即left存到上邊
for i in range(length):
matrix[top_r][top_c_start - i] = left[i]
4
邊元素依次旋轉(zhuǎn)法
事實上,我們可以對每一圈的每條邊上的每個元素單獨進行旋轉(zhuǎn),這樣的話,我們只需要臨時記錄其中的一個元素,以達到空間復(fù)雜度為O(1)的實現(xiàn)。
邊元素旋轉(zhuǎn)過程如圖所示:
def rotate(matrix):
n = len(matrix)
mi = n - 1 # 最大索引
# 每一圈loop
for loop in range(n // 2):
# 每一圈邊長
length = mi - 2 * loop
# 分別對邊上每四個對應(yīng)的元素進行旋轉(zhuǎn)
for i in range(length):
# bottom->left, right->bottom, top->right, left->top
left = matrix[loop + i][loop]
matrix[loop + i][loop] = matrix[mi - loop][loop + i]
matrix[mi - loop][loop + i] = matrix[mi - loop - i][mi - loop]
matrix[mi - loop - i][mi - loop] = matrix[loop][mi - loop - i]
matrix[loop][mi - loop - i] = left微信掃碼關(guān)注我哦
總結(jié)
以上是生活随笔為你收集整理的python矩阵旋转函数_Python3算法之十:矩阵旋转的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外眦悬吊后为什么能掉下来
- 下一篇: 英特尔展示 Lunar Lake 处理器