標籤:str 之間 旋轉 ima direct length 時間 style note
題目:矩陣旋轉
難度:Medium
題目內容:
You are given an n x n 2D matrix representing an image.
Rotate the image by 90 degrees (clockwise).
Note:
You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.
翻譯:你有一個n*n 的2D矩陣表示一個映像。
將映像旋轉90度(順時針)。
注意:
你必須在原地旋轉映像,這意味著你必須直接修改輸入2D矩陣。不要分配另一個2D矩陣並進行旋轉。
Example 1:
Given input matrix = [ [1,2,3], [4,5,6], [7,8,9]],rotate the input matrix in-place such that it becomes:[ [7,4,1], [8,5,2], [9,6,3]]
Example 2:
Given input matrix =[ [ 5, 1, 9,11], [ 2, 4, 8,10], [13, 3, 6, 7], [15,14,12,16]], rotate the input matrix in-place such that it becomes:[ [15,13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7,10,11]]
我的思路:旋轉90°,那就是把矩陣分為四塊,只對第一塊進行迴圈,然後用第一塊的元素下標【i】【j】的運算式分別表示其他塊的對應元素,然後把四個元素進行交換即可。
先將矩陣分為如下四塊:
A B
C D
現在對A內元素進行迴圈,其元素下標表示為【i】【j】
1、將A的此元素用temp儲存起來,
2、A的此元素取C地區對應的元素值,C區對應元素表示為A元素“先關於矩陣主對角線取對稱,然後再取縱向中心對摺”
主對角線取對稱,就是【i】【j】=》【j】【i】
縱向中心對摺,就是【i】【j】=》【n-1- i 】【j】
3、C區此元素取D地區對應的元素值,D區對應元素表示為A元素的中心對稱,即“先關於橫向中心對摺,然後再取縱向中心對摺”
橫線中心對摺,就是【i】【j】=》【i】【n-1- j】
4、D區此元素取B地區對應的元素值,B區對應元素表示為A元素“先關於橫向中心對摺,然後再取矩陣副對角線對稱”
副對角線對稱,就是【i】【j】=》【n-1-j】【n-1-i】
5、B區此元素取之前A區的值,即為 temp ,到此一輪交換結束。
需要注意的是,當矩陣的大小是偶數的時候,此時行數的對稱中心 x 為對稱線的上面的一個。
例如:
0
1
2
3 此時的 x = n-1 = 1,此時是需要進行交換的行範圍是【0~x】,列範圍也是【0~x】
而如果是奇數,則行範圍是【0~x-1】,列範圍沒變還是【0~x】
所以迴圈的時候需要注意判斷奇偶,然後跳過。
My Code:
1 public void rotate(int[][] matrix) { 2 int n = matrix.length; 3 if (n <= 1) { 4 return; 5 } 6 7 int even = 1; 8 if (matrix.length % 2 == 1) { 9 even = 0;10 }11 12 int x = (n-1)/2;13 for (int i = 0; i <= x; i++) {14 for (int j = 0; j <= x; j++) {15 if (even==0 && i==x) {16 continue;17 }18 int temp = matrix[i][j];19 matrix[i][j] = matrix[n-1-j][i];20 matrix[n-1-j][i] = matrix[n-1-i][n-1-j];21 matrix[n-1-i][n-1-j] = matrix[n-1-(n-1-j)][n-1-i];22 matrix[n-1-(n-1-j)][n-1-i] = temp;23 }24 }25 }
我的複雜度:O(N2)
編碼過程中的問題:
1、應該使用A的元素下標【i】【j】去表示其他塊所有,而不是用相對位置;
2、對“對稱”“對摺”的下標變化不熟悉,導致浪費不少時間;(還想了半天用 2x - i + even 來表示,其實直接 n-1-i 即可)
3、之前沒考慮到矩陣奇偶對迴圈範圍的影響,導致奇數的對稱線沒有交換;
4、當方法定義返回為void的時候,需要直接返回,寫return就行。
答案代碼:
1 public void rotate(int[][] matrix) { 2 int n = matrix.length; 3 if (n <= 1) { 4 return; 5 } 6 7 int x = (n-1)/2; 8 for (int i = 0; i <= x; i++) { 9 int[] tmp = matrix[i];10 matrix[i] = matrix[n-1-i];11 matrix[n-1-i] = tmp;12 }13 14 for (int i = 0; i < n; i++) {15 for (int j = i+1; j < n; j++) {16 int temp = matrix[i][j];17 matrix[i][j] = matrix[j][i];18 matrix[j][i] = temp;19 }20 }21 }
答案複雜度:O(N2)
答案思路:
首先將整個數組上下對稱交換:
1 2 3 7 8 9 4 5 6 => 4 5 67 8 9 1 2 3
然後再關於主對角線對稱交換:
7 8 9 7 4 14 5 6 => 8 5 21 2 3 9 6 3
優點:邏輯清晰明了
缺點:複雜度比我的方法高一點
擴充:
逆時針旋轉90°?
我的方法——ABCD塊之間的取值關係會發生變化。
答案方法——有兩種修改方法都行:
a:第一步和第二步交換,即先對角線,後對摺
b:把第一步的上下對稱交換改成左右對稱交換,第二步不變。
LeetCode第[48]題(Java):Rotate Image