給定一個 n × n 的二維矩陣表示一個圖像。
將圖像順時針旋轉 90 度。
說明:
你必須在原地旋轉圖像,這意味着你須要直接修改輸入的二維矩陣。請不要使用另外一個矩陣來旋轉圖像。java
示例 1: 給定 matrix = [ [1,2,3], [4,5,6], [7,8,9] ], 原地旋轉輸入矩陣,使其變爲: [ [7,4,1], [8,5,2], [9,6,3] ] 示例 2: 給定 matrix = [ [ 5, 1, 9,11], [ 2, 4, 8,10], [13, 3, 6, 7], [15,14,12,16] ], 原地旋轉輸入矩陣,使其變爲: [ [15,13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7,10,11] ]
分析:
題目意思很簡單,很容易理解。若是題目不給限制,那麼很好作,新建一個一樣大小的二維數組,將每個元素按照新的位置要求存入便可。但題目要求在原地完成,不建立新數組,固然也不能新建其餘的存儲元素的數據結構。這樣一會兒把題目提升了一大截。
既然是原地旋轉,那咱們就須要看一下每個元素是如何移動的。
咱們看示例1中給出的 3 3 的二維數組。
左上角的元素1,旋轉以後再右上角,那麼腳標的變化就是
[0][0] --> [0][2]
其餘的元素以此類推的旋轉:
[0][2] --> [2][2]
[2][2] --> [2][0]
[2][0] --> [0][0]
[0][1] --> [1][1]
[1][1] --> [2][1]
[2][1] --> [1][0]
[1][0] --> [0][1]
請在這個過程當中找到換位的規律。
再看示例2中的 4 4 的二維數組。
[0][0] --> [0][3]
[0][3] --> [3][3]
[3][3] --> [3][0]
[3][0] --> [0][0]
[0][1] --> [1][3]
[0][2] --> [2][3]
[1][1] --> [1][2]
使用概括法,咱們能夠發現規律:數組
[x][y] --> [y][n - 1 - x]
這樣,咱們獲得任何一個元素,只須要根據它的兩個腳標就能夠得出它要去到哪一個位置。
如今要選擇移動的方法,可使用臨時變量temp來做爲暫存變量,幫助換位置,但這樣的速度較慢。建議使用異或的方法。
a = a ^ b
b = a ^ b
a = a ^ b
這種方法效率高,速度快。
好的,找到目的地的腳標後,準備好移動元素了。
那麼如何移動?是用雙重for循環,按照0到n-1的順序讓全部元素交換嗎?這樣是不行的。若是按照順序那麼[0][0]將會存放到[0][n-1],那麼[0][n-1]本來的值怎麼辦?當按照順序遍歷到[0][n-1]時,去哪裏獲得其本來的值。因此按照順序遍歷移位是不行的。
那麼怎麼辦?仔細觀察能夠發現,一個矩陣裏面,旋轉會讓4個元素互相到達對方的位置,能夠把對應的4個元素歸爲一組。好比:
[0][0] --> [0][3]
[0][3] --> [3][3]
[3][3] --> [3][0]
[3][0] --> [0][0]
這是矩陣四個角的4個元素歸爲了一組,旋轉圖像就是它們的位置互換。咱們能夠利用這個規律,讓矩陣一次把一組4個元素的位置所有換完,而後再進行下一組4個元素。
咱們可使用兩兩換位的方法完成,讓一個元素連續換位置3次,就可讓4個元素都到達各自須要的地方。按照這個思路,那麼不能按照順時針方向的元素去交換,由於讓一個元素按照順時針方向交換位置3次,那麼全部的元素都想逆時針方向旋轉了90度,這不符合題意。只能按照逆時針方向交換位置3次。
那麼順時針方向腳標變化的規律是:數據結構
[x][y] --> [y][n - 1 - x]
能夠獲得逆時針方向腳標變化的規律是:ide
[x][y] --> [n - 1 - y][x]
那麼能夠獲得變化的代碼code
for (int j = 0; j < 3; j++) { x2 = n - 1 - y1; y2 = x1; matrix[x1][y1] = matrix[x1][y1] ^ matrix[x2][y2]; matrix[x2][y2] = matrix[x1][y1] ^ matrix[x2][y2]; matrix[x1][y1] = matrix[x1][y1] ^ matrix[x2][y2]; x1 = x2; y1 = y2; }
上面的for循環是固定進行3次,每一次兩兩換位置以後,用新位置的腳標繼續進行換位置。這樣一組4個元素就完成了旋轉。
好的,完成上面的代碼,就說明工做完成了一半了。
接下來要考慮的就是,如何找到4個元素爲一組的每一組。
繼續觀察:
3 3 的矩陣,有9個元素,須要旋轉2組元素。
4 4 的矩陣,有16個元素,須要旋轉4組元素。
能夠總結規律旋轉的次數:it
int count = n * n / 4;
最後,比較困難的部分就是如何定位到矩陣中的每個組須要旋轉的元素。
3 3 的矩陣,須要旋轉2組元素,須要定位到 [0][0], [0][1]
4 4 的矩陣,須要旋轉4組元素,須要定位到 [0][0], [0][1], [0][2], [1][1]
5 * 5 的矩陣,須要旋轉6組元素,須要定位到 [0][0], [0][1], [0][2], [0][3], [1][1], [1][2]
...
這一步比較困難,好在筆者在思考良久才尋到的法子。過程不解釋了,你們從下面完整的解答代碼中看吧。
如下是java解答:for循環
public void rotate(int[][] matrix) { int n = matrix.length; if (n <= 1) { return; } //旋轉次數 int count = n * n / 4; int x = 0; int y = 0; int z = 0; int x1, y1, x2, y2; for (int i = 0; i < count; i++) { if (z >= (n - 1) - 2 * x) { x += 1; z = 0; } y = z + x; z += 1; x1 = x; y1 = y; for (int j = 0; j < 3; j++) { x2 = n - 1 - y1; y2 = x1; matrix[x1][y1] = matrix[x1][y1] ^ matrix[x2][y2]; matrix[x2][y2] = matrix[x1][y1] ^ matrix[x2][y2]; matrix[x1][y1] = matrix[x1][y1] ^ matrix[x2][y2]; x1 = x2; y1 = y2; } } }