受Raymond Chen帖子的启发,假设你有一个4x4二维数组,写一个函数使它旋转90度。Raymond链接到伪代码中的解决方案,但我想看到一些真实的东西。

[1][2][3][4]
[5][6][7][8]
[9][0][1][2]
[3][4][5][6]

就变成:

[3][9][5][1]
[4][0][6][2]
[5][1][7][3]
[6][2][8][4]

更新:Nick的答案是最直接的,但是有没有比n²更好的方法呢?如果矩阵是10000x10000呢?


当前回答

你可以通过3个简单步骤做到这一点:

1)假设我们有一个矩阵

   1 2 3
   4 5 6
   7 8 9

2)求矩阵的转置

   1 4 7
   2 5 8
   3 6 9

3)交换行得到旋转矩阵

   3 6 9
   2 5 8
   1 4 7

Java源代码:

public class MyClass {

    public static void main(String args[]) {
        Demo obj = new Demo();
        /*initial matrix to rotate*/
        int[][] matrix = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
        int[][] transpose = new int[3][3]; // matrix to store transpose

        obj.display(matrix);              // initial matrix

        obj.rotate(matrix, transpose);    // call rotate method
        System.out.println();
        obj.display(transpose);           // display the rotated matix
    }
}

class Demo {   
    public void rotate(int[][] mat, int[][] tran) {

        /* First take the transpose of the matrix */
        for (int i = 0; i < mat.length; i++) {
            for (int j = 0; j < mat.length; j++) {
                tran[i][j] = mat[j][i]; 
            }
        }

        /*
         * Interchange the rows of the transpose matrix to get rotated
         * matrix
         */
        for (int i = 0, j = tran.length - 1; i != j; i++, j--) {
            for (int k = 0; k < tran.length; k++) {
                swap(i, k, j, k, tran);
            }
        }
    }

    public void swap(int a, int b, int c, int d, int[][] arr) {
        int temp = arr[a][b];
        arr[a][b] = arr[c][d];
        arr[c][d] = temp;    
    }

    /* Method to display the matrix */
    public void display(int[][] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}

输出:

1 2 3 
4 5 6 
7 8 9 

3 6 9 
2 5 8 
1 4 7 

其他回答

O(n²)时间和O(1)空间算法(没有任何变通方法和恶作剧的东西!)

旋转+90:

转置 反转每行

旋转-90:

方法一:

转置 反转每一列

方法二:

反转每行 转置

旋转180度:

方法一:旋转+90两次

方法2:反转每行,然后反转每列(转置)

旋转-180度:

方法一:旋转-90度2次

方法二:先反转每一列,再反转每一行

方法三:旋转+180,因为它们是相同的

Nick的答案也适用于NxM阵列,只需要做一点修改(与NxN相反)。

string[,] orig = new string[n, m];
string[,] rot = new string[m, n];

...

for ( int i=0; i < n; i++ )
  for ( int j=0; j < m; j++ )
    rot[j, n - i - 1] = orig[i, j];

考虑这个问题的一种方法是将轴(0,0)的中心从左上角移动到右上角。你只是简单地从一个转置到另一个。

这是我对矩阵90度旋转的尝试,这是c中的2步解决方案,首先转置矩阵,然后交换cols。

#define ROWS        5
#define COLS        5

void print_matrix_b(int B[][COLS], int rows, int cols) 
{
    for (int i = 0; i <= rows; i++) {
        for (int j = 0; j <=cols; j++) {
            printf("%d ", B[i][j]);
        }
        printf("\n");
    }
}

void swap_columns(int B[][COLS], int l, int r, int rows)
{
    int tmp;
    for (int i = 0; i <= rows; i++) {
        tmp = B[i][l];
        B[i][l] = B[i][r];
        B[i][r] = tmp;
    }
}


void matrix_2d_rotation(int B[][COLS], int rows, int cols)
{
    int tmp;
    // Transpose the matrix first
    for (int i = 0; i <= rows; i++) {
        for (int j = i; j <=cols; j++) {
            tmp = B[i][j];
            B[i][j] = B[j][i];
            B[j][i] = tmp;
        }
    }
    // Swap the first and last col and continue until
    // the middle.
    for (int i = 0; i < (cols / 2); i++)
        swap_columns(B, i, cols - i, rows);
}



int _tmain(int argc, _TCHAR* argv[])
{
    int B[ROWS][COLS] = { 
                  {1, 2, 3, 4, 5}, 
                      {6, 7, 8, 9, 10},
                          {11, 12, 13, 14, 15},
                          {16, 17, 18, 19, 20},
                          {21, 22, 23, 24, 25}
                        };

    matrix_2d_rotation(B, ROWS - 1, COLS - 1);

    print_matrix_b(B, ROWS - 1, COLS -1);
    return 0;
}

Python:

rotated = list(zip(*original[::-1]))

和逆时针方向:

rotated_ccw = list(zip(*original))[::-1]

这是如何工作的:

Zip (*original)将通过将列表中的对应项堆叠到新的列表中来交换2d数组的轴。(*操作符告诉函数将包含的列表分布到参数中)

>>> list(zip(*[[1,2,3],[4,5,6],[7,8,9]]))
[[1,4,7],[2,5,8],[3,6,9]]

语句[::-1]反转数组元素(请参阅扩展切片或这个问题):

>>> [[1,2,3],[4,5,6],[7,8,9]][::-1]
[[7,8,9],[4,5,6],[1,2,3]]

最后,将两者结合就得到了旋转变换。

改变[::-1]的位置将使列表在矩阵的不同层次上颠倒。

#include <iostream>
#include <iomanip>

using namespace std;
const int SIZE=3;
void print(int a[][SIZE],int);
void rotate(int a[][SIZE],int);

void main()
{
    int a[SIZE][SIZE]={{11,22,33},{44,55,66},{77,88,99}};
    cout<<"the array befor rotate\n";

    print(a,SIZE);
    rotate( a,SIZE);
    cout<<"the array after rotate\n";
    print(a,SIZE);
    cout<<endl;

}

void print(int a[][SIZE],int SIZE)
{
    int i,j;
    for(i=0;i<SIZE;i++)
       for(j=0;j<SIZE;j++)
          cout<<a[i][j]<<setw(4);
}

void rotate(int a[][SIZE],int SIZE)
{
    int temp[3][3],i,j;
    for(i=0;i<SIZE;i++)
       for(j=0;j<SIZE/2.5;j++)
       {
           temp[i][j]= a[i][j];
           a[i][j]= a[j][SIZE-i-1] ;
           a[j][SIZE-i-1] =temp[i][j];

       }
}