記一道有意思的演算法題Rotate Image(旋轉影象)

深藍發表於2015-04-09

題出自https://leetcode.com/problems/rotate-image/ 內容為:

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Follow up:
Could you do this in-place?

簡單的說就是給出一個n*n的二維陣列,然後把這個陣列進行90度順時針旋轉,而且不能使用額外的儲存空間。

最初拿到這道題想到的就是找出每個座標的旋轉規律。假設我們是2*2的矩陣:

a b c d

進行旋轉後,那麼就變成了:

c a d b

所以就轉換成對4個數字進行輪換,而不使用額外空間的問題。最常用的交換數值而不使用額外空間的演算法就是異或,比如要交換a,b的值,那麼可以寫為:

a=a^b; b=a^b; a=a^b;

現在是對4個數字進行輪換,輪換後的結果為a=c,b=a,c=d,d=b;

所以改寫成異或的演算法,那麼就是:

a = a ^ b ^ c ^ d; b = a ^ b ^ c ^ d; d = a ^ b ^ c ^ d; c = a ^ b ^ c ^ d; a = a ^ b ^ c ^ d;

接下來就是找出二維陣列中角標與a,b,c,d的關係,這個其實不難。另外,我們在進行旋轉處理時,我們只需要處理1/4的區域即可,因為處理一次就是調整了4個數,所以我們只處理二維陣列中左上角的數值。

下面就是具體的程式碼:

public void Rotate(int[,] matrix) { int n = matrix.GetLength (0); for (var i = 0; i < (n + 1)/2; i++) { for (var j = 0; j < n/2; j++) { //var a = matrix[i, j]; //var b = matrix[j, n - i - 1]; //var d = matrix[n - i - 1, n - j - 1]; //var c = matrix[n - j - 1, i]; matrix[i, j] = matrix[i, j] ^ matrix[j, n - i - 1] ^ matrix[n - i - 1, n - j - 1] ^ matrix[n - j - 1, i]; matrix[j, n - i - 1] = matrix[i, j] ^ matrix[j, n - i - 1] ^ matrix[n - i - 1, n - j - 1] ^ matrix[n - j - 1, i]; matrix[n - i - 1, n - j - 1] = matrix[i, j] ^ matrix[j, n - i - 1] ^ matrix[n - i - 1, n - j - 1] ^ matrix[n - j - 1, i]; matrix[n - j - 1, i] = matrix[i, j] ^ matrix[j, n - i - 1] ^ matrix[n - i - 1, n - j - 1] ^ matrix[n - j - 1, i]; matrix[i, j] = matrix[i, j] ^ matrix[j, n - i - 1] ^ matrix[n - i - 1, n - j - 1] ^ matrix[n - j - 1, i]; } } }

使用異或並不是很直觀,另外一個比較直觀的交換兩個資料的方法是加減法:

a=a+b; b=a-b; a=a-b;

我們使用異或而不使用更直觀的加減法是因為a+b的時候可能溢位,那麼接下來的結果就不對了,所以不能用加減法而應該用異或。

相關文章