如何在不使用任何额外空间的情况下将矩阵旋转90度?

时间:2010-08-15 18:33:51

标签: arrays algorithm

  

可能重复:
  Algorithm to rotate an image 90 degrees in place? (No extra memory)

说90度我的意思是说:

A = {1,2,3,
     4,5,6,
     7,8,9}

然后在90度旋转后A变为:

A = {7,4,1,
     8,5,2,
     9,6,3}

7 个答案:

答案 0 :(得分:104)

转置和交换行或列(取决于您是想要向左还是向右旋转)。

即克。

1) original matrix

1 2 3
4 5 6
7 8 9

2) transpose

1 4 7
2 5 8
3 6 9

3-a) change rows to rotate left

3 6 9
2 5 8
1 4 7

3-b) or change columns to rotate right

7 4 1
8 5 2
9 6 3

所有这些操作都可以在不分配内存的情况下完成。

答案 1 :(得分:53)

a成为基于nxn数组0的索引

f = floor(n/2)
c = ceil(n/2)

for x = 0 to f - 1
  for y = 0 to c - 1
    temp = a[x,y]
    a[x,y] = a[y,n-1-x]
    a[y,n-1-x] = a[n-1-x,n-1-y]
    a[n-1-x,n-1-y] = a[n-1-y,x]
    a[n-1-y,x] = temp

编辑如果你想避免使用temp,这次会在python中运行(它也会以正确的方向旋转)。

def rot2(a):
  n = len(a)
  c = (n+1) / 2
  f = n / 2
  for x in range(c):
    for y in range(f):
      a[x][y] = a[x][y] ^ a[n-1-y][x]
      a[n-1-y][x] = a[x][y] ^ a[n-1-y][x]
      a[x][y] = a[x][y] ^ a[n-1-y][x]

      a[n-1-y][x] = a[n-1-y][x] ^ a[n-1-x][n-1-y]
      a[n-1-x][n-1-y] = a[n-1-y][x] ^ a[n-1-x][n-1-y]
      a[n-1-y][x] = a[n-1-y][x] ^ a[n-1-x][n-1-y]

      a[n-1-x][n-1-y] = a[n-1-x][n-1-y]^a[y][n-1-x]
      a[y][n-1-x] = a[n-1-x][n-1-y]^a[y][n-1-x]
      a[n-1-x][n-1-y] = a[n-1-x][n-1-y]^a[y][n-1-x]

注意:这仅适用于整数矩阵。

答案 2 :(得分:11)

算法是旋转每个“环”,从最外面到最里面。

AAAAA
ABBBA
ABCBA
ABBBA
AAAAA

算法将首先旋转所有A,然后B旋转然后旋转C.旋转一个环需要一次移动4个值。

索引i的范围是0..ring-width-1,例如对于A,宽度为5。

  (i,0) -> temp
  (0, N-i-1) -> (i, 0)
  (N-i-1, N-1) -> (0, N-i-1)
  (N-1, i) -> (N-i-1, N-1)
  temp -> (N-1, i)  

然后对每个连续的内环重复此操作,使坐标偏移,使环宽减小2.

[代码中出现了另一个答案,所以我不会重复。]

答案 3 :(得分:3)

请参阅this article进行就地矩阵换位;也谷歌的“就地矩阵换位”。它可以很容易地适应旋转90度。要转置方形矩阵,只需将b[i][j]b[j][i] b[k][l] a[n*k+l]交换为{{1}}。在非方形矩阵上,它要困难得多。 “没有任何额外的空间”是一个相当强烈的要求,也许你的意思是O(1)空间? (假设整数是固定大小)用C ++实现:here

答案 4 :(得分:3)

使用@Narek上面描述的方法在C中完成实现

#include <stdio.h>

int n;
unsigned int arr[100][100];

void rotate() {

    int i,j,temp;

    for(i=0; i<n; i++) {
        for(j=i; j<n; j++) {
            if(i!=j) {
                arr[i][j]^=arr[j][i];
                arr[j][i]^=arr[i][j];
                arr[i][j]^=arr[j][i];
            }
        }
    }


    for(i=0; i<n/2; i++) {
        for(j=0; j<n; j++) {
            arr[j][i]^=arr[j][n-1-i];
            arr[j][n-1-i]^=arr[j][i];
            arr[j][i]^=arr[j][n-1-i];
        }
    }

}

void display(){

    int i,j;

    for(i=0;i<n;i++) {
        for(j=0;j<n;j++) {
            printf("%d",arr[i][j]);}
            printf("%s","\n");
        }
    }

    int main(int argc, char *argv[]){

    int i,j;

    printf("%s","Enter size of matrix:");
    scanf("%d",&n);

    printf("%s","Enter matrix elements\n");

    for(i=0;i<n;i++) {
        for(j=0;j<n;j++) {
            scanf("%d",&arr[i][j]);
        }
    }

    rotate();
    display();

    return 0;
}

答案 5 :(得分:2)

你需要一个临时变量,然后只是跳转元素。

temp = A[0];
A[0] = A[6];
A[6] = A[8];
A[8] = A[2];
A[2] = temp;
temp = A[1];
A[1] = A[3];
A[3] = A[7];
A[7] = A[5];
A[5] = temp;

答案 6 :(得分:0)

我遇到了以下实施:

对于方形矩阵:

for n = 0 to N - 2
    for m = n + 1 to N - 1
        swap A(n,m) with A(m,n)

对于矩形矩阵:

for each length>1 cycle C of the permutation
    pick a starting address s in C
    let D = data at s
    let x = predecessor of s in the cycle
    while x ≠ s
        move data from x to successor of x
        let x = predecessor of x
    move data from D to successor of s

有关详细信息,请参阅此处:http://en.wikipedia.org/wiki/In-place_matrix_transposition