【问题标题】:How to rotate a matrix 90 degrees without using any extra space? [duplicate]如何在不使用任何额外空间的情况下将矩阵旋转 90 度? [复制]
【发布时间】:2011-03-30 03:45:32
【问题描述】:

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

说 90 度是指如果:

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

那么A旋转90度后变成:

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

【问题讨论】:

  • 不,矩阵甚至可以是矩形的。
  • 你使用什么语言?
  • 只有方阵可以原地旋转。我们会在旋转后将矩形矩阵的维度从 MxN 更改为 NxM,因此在这种情况下我们需要创建一个新矩阵。

标签: arrays algorithm


【解决方案1】:

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]

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

【讨论】:

  • 没有使用 temp 错误..?我们不是在使用额外的空间吗?
  • 这是一个位置。它与使用 x 和 y、f 和 c 一样是错误的。如果你的数组有整数,你可以使用 xor 交换技巧,但你仍然需要 x 和 y 并且至少隐式地需要 f 和 c
  • 通常在讨论算法时,常量空间要求通常不被视为“额外空间”。额外空间通常是整个或部分数据结构的完整副本。
  • 另外,我的方向错了,我会尽快更新版本。
  • 在 python 中我们可以通过 a,b = b,a 交换两个元素
【解决方案2】:

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

e。 g.

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

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

【讨论】:

  • 此算法将触摸每个元素两次。面试官可能会问是否可以只触摸一次元素。
  • @Narek 是否适用于行的大小!= 列的大小??
  • @Narek 嗯。这意味着rows和cols总是会有一些固定的初始大小,否则如果rows = 3和cols =2那么我们就不能原地旋转
  • 对于后代:'change rows' 意味着'用第 n 行翻转第 0 行,用第 n-1 行翻转第 1 行,等等'。列类似。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    使用上面@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;
    }
    

    【讨论】:

    • 您能否在每个 for 循环中添加注释来补充您的代码?
    • @MusséRedi 只是与XOR 操作^ 交换,没有更具体的内容。首先,在转置时进行交换。其次,在换列的同时。我对实现的更正:你应该从i + 1开始j并在转置时删除if (i != j),你也可以用std::swap替换转换
    【解决方案5】:

    我遇到了以下实现:

    对于方阵:

    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

    【讨论】:

    • 您描述并链接到矩阵转置,但 OP 要求矩阵旋转。
    【解决方案6】:

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

    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。

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

    【讨论】:

    • 如果不是NxN方阵,每个环都很难旋转
    • @PeterLee,我认为旋转非方阵是不可能的
    • @ChanderShivdasani,我同意你的看法。但如果是方阵,环形旋转是个好主意。
    • @ChanderShivdasani:旋转非方阵是可能的。您只需将其存储在具有其他值的方阵中NULL
    【解决方案7】:

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

    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;
    

    【讨论】:

    • 数组的大小不是固定的.. 它可以变化.. 64x64 数组呢..?我刚才提到了数组作为例子。
    猜你喜欢
    • 2012-10-24
    • 2019-03-08
    • 2020-09-04
    • 1970-01-01
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 2013-02-09
    相关资源
    最近更新 更多