2017-02-27 81 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