45

Possible Duplicate:
Algorithm to rotate an image 90 degrees in place? (No extra memory)

By saying 90 degrees i mean to say if:

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

then after 90 degree rotation A becomes:

A = {7,4,1,
     8,5,2,
     9,6,3}
Community
  • 1
  • 1
Vaibhav
  • 6,620
  • 11
  • 47
  • 72

7 Answers7

106

Transpose and interchange rows or columns (depends whether you want to rotate left or right).

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

All these operations can be done without allocating memory.

Narek
  • 38,779
  • 79
  • 233
  • 389
  • 13
    This algorithm will touch each element twice. An interviewer might ask if it's possible to just touch the element once. – Peter Lee Aug 07 '13 at 05:52
  • @Narek will it work for when the size of rows != size of cols?? – Narendra Jaggi Jan 17 '16 at 14:30
  • @Narek hmm. that means there will be some fixed initial size for rows and cols always otherwise if rows = 3 and cols =2 then we can't rotate in place – Narendra Jaggi Jan 17 '16 at 18:37
  • 2
    For posterity: 'change rows' means 'flip row 0 with row n, row 1 with row n-1, etc'. Similar for columns. – Qqwy Jun 16 '16 at 20:23
54

let a be an nxn array 0 based indexing

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

Edit If you want to avoid using temp, this works (it also rotates in the correct direction) this time in 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]

Note: This only works for matrices of integers.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
deinst
  • 18,402
  • 3
  • 47
  • 45
  • 1
    isn't using temp wrong..? aren't we using an extra space? – Vaibhav Aug 15 '10 at 19:00
  • 5
    It is one location. It is as wrong as using x and y, f and c. If your array has integers you could use the xor swap trick, but you would still need x and y and at least implicitly f and c – deinst Aug 15 '10 at 19:03
  • 32
    Usually when discussing algorithms constant space requirements are usually not considered "extra space". Extra space is usually a complete copy of the whole or parts of the datastructure. – Albin Sunnanbo Aug 15 '10 at 19:05
  • also, I'm rotating in the wrong direction, I'll put an updated version soon. – deinst Aug 15 '10 at 19:14
  • 3
    in python we can swap two elements by just doing a,b = b,a – syllogismos Jun 06 '13 at 21:30
  • Pretty sure this is incorrect. Run the code. – zallarak Sep 16 '15 at 02:50
  • I've implemented variations of your code in [Hack Fast Algos](https://github.com/cozylife/hackfastalgos/blob/master/lib/matrixrotate.php) to demonstrate how to rotate and flip a matrix in many ways. – Rick Mac Gillis Nov 06 '15 at 02:09
  • @zallarak I ran the code and it works when N is even, though I haven't been able to decipher why it works >. – pgpb.padilla Nov 25 '15 at 06:05
  • @deinst can you tell me what's the idea behind the first algorithm? Does it rely on some sort of symmetry? – pgpb.padilla Nov 25 '15 at 06:08
  • Where is the (n+1)/2 and n/2 coming from? – PDN Mar 07 '16 at 03:12
  • @pdn They are half of n. The reason that (n+1)/2 is there is that in the outer loop we need to work on the center row/column when n is odd. – deinst Mar 07 '16 at 03:54
11

The algorithm is to rotate each "ring", working from the outermost to the innermost.

AAAAA
ABBBA
ABCBA
ABBBA
AAAAA

The algorithm would rotate all the A's first, then B's then C's. Rotating a ring requires moving 4 values at once.

The index i ranges from 0..ring-width-1, e.g. for A the width is 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)  

This is then repeated for each successive inner ring, offsetting the co-ordinates reducing the ring width by 2.

[Another answer has appeared with the code, so I'll not repeat that.]

mdma
  • 56,943
  • 12
  • 94
  • 128
3

Complete implementation in C using the method described by @Narek above

#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;
}
Zoltan Toth
  • 46,981
  • 12
  • 120
  • 134
user720694
  • 2,035
  • 6
  • 35
  • 57
  • 1
    Could you supplement your code with comment at each for loop? – easytarget Jul 19 '14 at 12:11
  • 1
    @MusséRedi just swapping with `XOR` operation `^`, nothing more specific. Firstly, swapping while transposing. Secondly, while changing columns. My corrections towards the realisation: you should start `j` from `i + 1` and remove `if (i != j)` while transposing, you can also replace transformations with `std::swap` – Beraliv Oct 26 '15 at 08:30
3

See this article for in-place matrix transposition; also google for "in-place matrix transposition". It can be easily adapted to perform rotation by 90 degrees. To transpose square matrices, you just interchange b[i][j] with b[j][i] where b[k][l] is a[n*k+l]. On nonsquare matrices, it's considerably more difficult. "Without any extra space" is a rather strong requirement, maybe you meant O(1) space? (assuming integers are fixed size) Implementation in C++: here.

sdcvvc
  • 25,343
  • 4
  • 66
  • 102
1

You need one temp variable, then it is just to jump elements around.

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;
Albin Sunnanbo
  • 46,430
  • 8
  • 69
  • 108
  • the size of array isn't fixed.. it can vary.. what about 64x64 array..? I just mentioned the array as an example. – Vaibhav Aug 15 '10 at 18:42
-1

I came across the following implementation:

For square matrices:

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

For rectangular matrices:

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 more info, one can refer here: http://en.wikipedia.org/wiki/In-place_matrix_transposition

Vaibhav
  • 6,620
  • 11
  • 47
  • 72