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

Arrays 如何在不使用任何额外空间的情况下将矩阵旋转90度?,arrays,algorithm,Arrays,Algorithm,可能重复: 我所说的90度是指: A = {1,2,3, 4,5,6, 7,8,9} 旋转90度后,A变成: A = {7,4,1, 8,5,2, 9,6,3} 您需要一个temp变量,然后它只是用来跳转元素 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]

可能重复:

我所说的90度是指:

A = {1,2,3,
     4,5,6,
     7,8,9}
旋转90度后,A变成:

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

您需要一个temp变量,然后它只是用来跳转元素

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;

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

e。g


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

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]

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

算法是旋转每个“环”,从最外层到最内层

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


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

我遇到了以下实现:

对于平方矩阵:

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
对于矩形矩阵:

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

有关更多信息,请参阅此处:

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

使用上面@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;
}
#包括
int n;
无符号整数arr[100][100];
void rotate(){
int i,j,温度;


对于(i=0;数组的大小不是固定的。它可以变化。64x64数组呢?我刚才提到了数组作为一个例子。使用temp不是错误吗?我们不是使用了额外的空间吗?它是一个位置。它与使用x和y、f和c一样错误。如果数组有整数,可以使用xor交换技巧,但仍然需要x和y,至少需要im在讨论算法时,通常不考虑“额外空间”的恒定空间要求。额外的空间通常是整个或部分数据结构的完整副本。此外,我的旋转方向错误,我将很快发布一个更新版本。在python中,我们可以通过执行a,b=b,aNo来交换两个元素,矩阵甚至可以是矩形。您使用的是什么语言?只有方形矩阵可以旋转到位。我们将更改旋转后矩形矩阵的维数,从MxN到NxM,因此在这种情况下我们需要创建一个新的矩阵。该算法将对每个元素进行两次运算。面试官可能会问,是否可以只对元素进行一次运算。@Narek行的大小!=cols的大小???@Narek-hmm。这意味着将有一些固定的init行和列的ial大小总是相反,如果行=3,列=2,那么我们就不能为后代原地旋转:“更改行”意味着“用n行翻转行0,用n-1行翻转行1,等等”。类似于列。如果不是方形NxN矩阵,则很难旋转每个行ring@PeterLee,我不认为旋转非方矩阵是偶数possible@ChanderShivdasani,我同意你的看法。但是如果它是一个方阵,环旋转是一个好主意。@ChanderShivdasani:旋转一个非方阵是可能的。。你只需要将它与其他值一起存储在一个方阵中
NULL
你能在每个for循环中用注释补充你的代码吗?@MusséRedi只是用
XOR
操作进行交换n
^
,没有什么更具体的。首先,在转置时交换。其次,在更改列时。我对实现的更正:您应该从
i+1
开始
j
,如果(i!=j),则删除
在转置时,您也可以用您描述并链接到矩阵转置的
std::swap
替换变换,但OP要求矩阵旋转。