LeetCode初級算法之數組:48 旋轉圖像

旋轉圖像

題目地址:https://leetcode-cn.com/problems/rotate-image/java

給定一個 n × n 的二維矩陣表示一個圖像。
將圖像順時針旋轉 90 度。算法

說明:數組

你必須在原地旋轉圖像,這意味着你須要直接修改輸入的二維矩陣。請不要使用另外一個矩陣來旋轉圖像。數據結構

示例 1:指針

給定 matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

原地旋轉輸入矩陣,使其變爲:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

示例 2:code

給定 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]
]

四指針

這一題與前面寫到的旋轉數組一題類似,以前是一維的,如今至關因而二維版。一樣是兩種思路一種是直接設置值到最終的地方,被覆蓋的值先用備份變量拿出來再往它的目的地去設。第二種就是反轉的思路。索引

旋轉上圖過程leetcode

(1) 
backup = m[0][1]
m[0][1] = m[0][0]
(2)
temp = backup
backup = m[1][1]
m[1][1] = temp
(3)
temp = backup
backup = m[1][0]
m[1][0] = temp
(4)
m[0][0] = backup

因爲是2×2因此一次旋轉設值完事,若是是3×3字符串

和以前那一題仍是有點差異,這邊設置值的傳遞固定是四個完成一組,而後須要判斷一圈有多少組get

1×1 0組
2×2 1組
3×3 2組

四次設置值是一個單元操做,以後指針變更第一個指針是水平向右移動,第二個指針是垂直向下其餘依次,直到頭length-1。那麼外循環條件是有幾圈2×2,3×3都只有一圈,4×4與5×5是兩圈。也就是length/2圈,內循環爲每圈要移動多少組數字它取決於終點索引,而且每往內一圈length都會少2兩邊都會靠近1格。

  • 外圈(第一圈)起點matrix[0][0] 終點matrix[0][2] 有三組
  • 內圈(第二圈)起點matrix[1][1] 終點matrix[1][1] 只有一組

也就是當外循環完畢內循環的起點是和外循環相同,也就是j = i而後j在日後遞增直到終點,終點會往內圈慢慢遞減

咱們這裏只看首指針的變化,其餘同樣推總結在代碼裏

  • 第一圈從[0][0]--->[0][4] 5組
  • 第二圈從[1][1]--->[1][3] 3組
  • 第三圈就[2][2] 1組
public void rotate(int[][] matrix) {
    int n = matrix.length;
    int s = n;
    for (int i = 0; i < n/2; i++,s--) {
    	for (int j = i; j < s-1; j++) {      
            int backup = matrix[j][n-i-1];
            matrix[j][n-i-1] = matrix[i][j];
            
            int temp = matrix[n-i-1][n-j-1];
            matrix[n-i-1][n-j-1] = backup;
            backup = temp;
            
            temp = matrix[n-j-1][i];
            matrix[n-j-1][i] = backup;
            backup = temp;
            
            matrix[i][j] = backup;
        }
    }
}

整體實現了這樣一個主線,但就是咱們去存將被覆蓋的值其實不須要另外添加一個變量backup咱們能夠直接把它存在首指針的地方,那個地方到最後才被設值中途是啥都沒有關係咱們就暫時用它存(空間已經存在了不用白不用)。

public void rotate(int[][] matrix) {
    int n = matrix.length;
    int s = n;
    for (int i = 0; i < n/2; i++,s--) {
    	for (int j = i; j < s-1; j++) {        
            int temp = matrix[i][j]
            matrix[i][j] = matrix[j][n-i-1];
            matrix[j][n-i-1] = temp;
            
            temp = matrix[n-i-1][n-j-1];
            matrix[n-i-1][n-j-1] = matrix[i][j];
            matrix[i][j] = temp;
            
            temp = matrix[n-j-1][i];
            matrix[n-j-1][i] = matrix[i][j];
   	    matrix[i][j] = temp;
        }
    }
}

兩次反轉

第二種方式就反轉和旋轉數組一題同樣咱們直接觀察輸入圖與目標圖經過怎樣的變換能夠獲得

旋轉90度的關係確定是沒有直接方式的,這裏咱們確定是用到的設值。經過圖形變換反轉相似的方式就兩數交換完成就可能進行幾組反轉比起上面直接的一步的到位的設值方式在單元操做上兩數交換比起四數看起來簡一點。但有進行多組遍歷的可能。它是轉90而不是180若是是180就上下反轉而後左右反轉。因此這裏只能對角反轉加左右反轉前後無所謂

不管怎麼轉均可以實現總之是經過兩個數的交換就很簡單,而後要進行兩次。下面代碼按照第一條進行,第一個變換隻須要遍歷左上一半便可每一個完成和下面的交換便可所以列的起點是遞增的j = i,第二個變換循環時列只須要左邊一半就換行因此j = length/2

public void rotate(int[][] matrix) {
    int n = matrix.length;
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            int tmp = matrix[j][i];
            matrix[j][i] = matrix[i][j];
            matrix[i][j] = tmp;
        }
    }
   
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n / 2; j++) {
            int tmp = matrix[i][j];
            matrix[i][j] = matrix[i][n - j - 1];
            matrix[i][n - j - 1] = tmp;
        }
    }
}

總結

整體來講都是一個原地算法,時間也都是O(n^2),像這一題與以前一題都是屬於數組內原地的變化位置即多值交換以及換成多組反轉即兩值交換的組合。主要也是體會在數組這樣的數據結構當中咱們能夠有的算法思想:遍歷、逆序、原地交換、快慢指針。萬變不離其中,那麼從更新《LeetCode平常》系列開始到這篇爲止LeetCode初級算法合集中的數組篇章完結即將開啓下一篇章字符串相關算法

相關文章
相關標籤/搜索