2017-02-27 77 views
1

我很困惑這一個不尋常的任務一天來找出一個合適的算法。假設我有二維數組:更改數組中的元素

int[][] jagged = new int[4][]; 
jagged[0] = new int[4] { 1, 2, 3, 4 }; 
jagged[1] = new int[4] { 5, 6, 7, 8 }; 
jagged[2] = new int[4] { 9, 10, 11, 12 }; 
jagged[3] = new int[4] { 13, 14, 15, 16 }; 

如何以逆時針方向旋轉矩陣如下?

1 2 3 4    2 3 4 8   3 4 8 12 
5 6 7 8 -->  1 7 11 12 --> 2 11 10 16 
9 10 11 12   5 6 10 16   1 7 6 15 
13 14 15 16   9 13 14 15  5 9 13 14 

二維數組可以有不同的尺寸。我的意思是2x3或3x4。

我試着用下面的算法,但它只是旋轉到90度:

int [,] newArray = new int[4,4]; 

for (int i=3;i>=0;--i) 
{ 
    for (int j=0;j<4;++j) 
    { 
     newArray[j,3-i] = array[i,j]; 
    } 
} 

如果我改變的增量,那麼它確實給我什麼。也許有另一種解決方案?

回答

1

我知道這個問題的答案,但我想這樣做對的nxm一般矩陣。它考慮了矩陣只有一列或一行的情況。

public static void Rotate(int[,] matrix) 
{ 
    // Specific cases when matrix has one only row or column 
    if (matrix.GetLength(0) == 1 || matrix.GetLength(1) == 1) 
     RotateOneRowOrColumn(matrix); 
    else 
    { 
     int min = Math.Min(matrix.GetLength(0), matrix.GetLength(1)), 
     b = min/2, r = min % 2; 

     for (int d = 0; d < b + r; d++) 
     { 
      int bkp = matrix[d, d]; 
      ShiftRow(matrix, d, d, matrix.GetLength(1) - d - 1, true); 
      ShiftColumn(matrix, matrix.GetLength(1) - d - 1, d, matrix.GetLength(0) - d - 1, false); 
      ShiftRow(matrix, matrix.GetLength(0) - d - 1, d, matrix.GetLength(1) - d - 1, false); 
      ShiftColumn(matrix, d, d + 1, matrix.GetLength(0) - d - 1, true); 
      if (matrix.GetLength(0) - 2 * d - 1 >= 1) 
       matrix[d + 1, d] = bkp; 
     } 
    } 
} 

private static void RotateOneRowOrColumn(int[,] matrix) 
{ 
    bool isRow = matrix.GetLength(0) == 1; 
    int s = 0, e = (isRow ? matrix.GetLength(1) : matrix.GetLength(0)) - 1; 

    while (s < e) 
    { 
     if (isRow) 
      Swap(matrix, 0, s, 0, e); 
     else 
      Swap(matrix, s, 0, e, 0); 
     s++; e--; 
    } 
} 

public static void Swap(int[,] matrix, int from_x, int from_y, int to_x, int to_y) 
{ 
    //It doesn't verifies whether the indices are correct or not 
    int bkp = matrix[to_x, to_y]; 
    matrix[to_x, to_y] = matrix[from_x, from_y]; 
    matrix[from_x, from_y] = bkp; 
} 

public static void ShiftColumn(int[,] matrix, int col, int start, int end, bool down) 
{ 
    for (int i = down ? end - 1 : start + 1; (down && i >= start) || (!down && i <= end); i += down ? -1 : 1) 
    { matrix[i + (down ? 1 : -1), col] = matrix[i, col]; } 
} 

public static void ShiftRow(int[,] matrix, int row, int start, int end, bool left) 
{ 
    for (int j = left ? start + 1 : end - 1; (left && j <= end) || (!left && j >= start); j += (left ? 1 : -1)) 
    { matrix[row, j + (left ? -1 : 1)] = matrix[row, j]; } 
} 
+1

@StepUp,根據我做的一些測試,我相信我的代碼適用於每個二維矩陣。做你自己的測試,如果你發現任何錯誤,讓我知道。 – dcg

+0

非常感謝!你是超人! :) 非常感謝! – StepUp

2

假設陣列的每個「方形」都是獨立旋轉的。
你可以使用下面的代碼片段:

const int ArraySize = 4; 
int[,] array = 
       { 
        { 2, 3, 4, 8 }, 
        { 1, 7, 11, 12 }, 
        { 5, 6, 10, 16 }, 
        { 9, 13, 14, 15 } 
       }; 

for (int r = (ArraySize - 1)/2; r >= 0; r--) 
{ 
    int start = r; 
    int end = ArraySize - r - 1; 
    int saveTopLeft = array[start, start]; 

    // Top 
    for (int i = start; i <= end - 1; i++) 
     array[start, i] = array[start, i + 1]; 

    // Right 
    for (int i = start; i <= end - 1; i++) 
     array[i, end] = array[i + 1, end]; 

    // Bottom 
    for (int i = end; i >= start + 1; i--) 
     array[end, i] = array[end, i - 1]; 

    // Left 
    for (int i = end; i >= start + 2; i--) 
     array[i, start] = array[i - 1, start]; 

    // Saved element 
    array[start + 1, start] = saveTopLeft; 
} 
+0

是否有可能使我儘可能多的旋轉。例如,兩次或三次旋轉? – StepUp

+0

德米特里,如果我有矩陣的另一個維度,那麼我應該添加/刪除'for'循環?也許你知道任何其他解決方案,而不重寫代碼? – StepUp

+0

@StepUp是的,可以重複運行此代碼。如果你有矩陣的第三維,恐怕解決方案會更加複雜。 – Dmitry