How do you rotate a two dimensional array?

后端 未结 30 3064
耶瑟儿~
耶瑟儿~ 2020-11-22 02:43

Inspired by Raymond Chen\'s post, say you have a 4x4 two dimensional array, write a function that rotates it 90 degrees. Raymond links to a solution in pseudo code, but I\'d

相关标签:
30条回答
  • 2020-11-22 03:40

    Python:

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

    and counterclockwise:

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

    How this works:

    zip(*original) will swap axes of 2d arrays by stacking corresponding items from lists into new lists. (The * operator tells the function to distribute the contained lists into arguments)

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

    The [::-1] statement reverses array elements (please see Extended Slices or this question):

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

    Finally, combining the two will result in the rotation transformation.

    The change in placement of [::-1] will reverse lists in different levels of the matrix.

    0 讨论(0)
  • 2020-11-22 03:41

    As I said in my previous post, here's some code in C# that implements an O(1) matrix rotation for any size matrix. For brevity and readability there's no error checking or range checking. The code:

    static void Main (string [] args)
    {
      int [,]
        //  create an arbitrary matrix
        m = {{0, 1}, {2, 3}, {4, 5}};
    
      Matrix
        //  create wrappers for the data
        m1 = new Matrix (m),
        m2 = new Matrix (m),
        m3 = new Matrix (m);
    
      //  rotate the matricies in various ways - all are O(1)
      m1.RotateClockwise90 ();
      m2.Rotate180 ();
      m3.RotateAnitclockwise90 ();
    
      //  output the result of transforms
      System.Diagnostics.Trace.WriteLine (m1.ToString ());
      System.Diagnostics.Trace.WriteLine (m2.ToString ());
      System.Diagnostics.Trace.WriteLine (m3.ToString ());
    }
    
    class Matrix
    {
      enum Rotation
      {
        None,
        Clockwise90,
        Clockwise180,
        Clockwise270
      }
    
      public Matrix (int [,] matrix)
      {
        m_matrix = matrix;
        m_rotation = Rotation.None;
      }
    
      //  the transformation routines
      public void RotateClockwise90 ()
      {
        m_rotation = (Rotation) (((int) m_rotation + 1) & 3);
      }
    
      public void Rotate180 ()
      {
        m_rotation = (Rotation) (((int) m_rotation + 2) & 3);
      }
    
      public void RotateAnitclockwise90 ()
      {
        m_rotation = (Rotation) (((int) m_rotation + 3) & 3);
      }
    
      //  accessor property to make class look like a two dimensional array
      public int this [int row, int column]
      {
        get
        {
          int
            value = 0;
    
          switch (m_rotation)
          {
          case Rotation.None:
            value = m_matrix [row, column];
            break;
    
          case Rotation.Clockwise90:
            value = m_matrix [m_matrix.GetUpperBound (0) - column, row];
            break;
    
          case Rotation.Clockwise180:
            value = m_matrix [m_matrix.GetUpperBound (0) - row, m_matrix.GetUpperBound (1) - column];
            break;
    
          case Rotation.Clockwise270:
            value = m_matrix [column, m_matrix.GetUpperBound (1) - row];
            break;
          }
    
          return value;
        }
    
        set
        {
          switch (m_rotation)
          {
          case Rotation.None:
            m_matrix [row, column] = value;
            break;
    
          case Rotation.Clockwise90:
            m_matrix [m_matrix.GetUpperBound (0) - column, row] = value;
            break;
    
          case Rotation.Clockwise180:
            m_matrix [m_matrix.GetUpperBound (0) - row, m_matrix.GetUpperBound (1) - column] = value;
            break;
    
          case Rotation.Clockwise270:
            m_matrix [column, m_matrix.GetUpperBound (1) - row] = value;
            break;
          }
        }
      }
    
      //  creates a string with the matrix values
      public override string ToString ()
      {
        int
          num_rows = 0,
          num_columns = 0;
    
        switch (m_rotation)
        {
        case Rotation.None:
        case Rotation.Clockwise180:
          num_rows = m_matrix.GetUpperBound (0);
          num_columns = m_matrix.GetUpperBound (1);
          break;
    
        case Rotation.Clockwise90:
        case Rotation.Clockwise270:
          num_rows = m_matrix.GetUpperBound (1);
          num_columns = m_matrix.GetUpperBound (0);
          break;
        }
    
        StringBuilder
          output = new StringBuilder ();
    
        output.Append ("{");
    
        for (int row = 0 ; row <= num_rows ; ++row)
        {
          if (row != 0)
          {
            output.Append (", ");
          }
    
          output.Append ("{");
    
          for (int column = 0 ; column <= num_columns ; ++column)
          {
            if (column != 0)
            {
              output.Append (", ");
            }
    
            output.Append (this [row, column].ToString ());
          }
    
          output.Append ("}");
        }
    
        output.Append ("}");
    
        return output.ToString ();
      }
    
      int [,]
        //  the original matrix
        m_matrix;
    
      Rotation
        //  the current view of the matrix
        m_rotation;
    }
    

    OK, I'll put my hand up, it doesn't actually do any modifications to the original array when rotating. But, in an OO system that doesn't matter as long as the object looks like it's been rotated to the clients of the class. At the moment, the Matrix class uses references to the original array data so changing any value of m1 will also change m2 and m3. A small change to the constructor to create a new array and copy the values to it will sort that out.

    0 讨论(0)
  • 2020-11-22 03:41

    C code for matrix rotation 90 degree clockwise IN PLACE for any M*N matrix

    void rotateInPlace(int * arr[size][size], int row, int column){
        int i, j;
        int temp = row>column?row:column;
        int flipTill = row < column ? row : column;
        for(i=0;i<flipTill;i++){
            for(j=0;j<i;j++){
                swapArrayElements(arr, i, j);
            }
        }
    
        temp = j+1;
    
        for(i = row>column?i:0; i<row; i++){
                for(j=row<column?temp:0; j<column; j++){
                    swapArrayElements(arr, i, j);
                }
        }
    
        for(i=0;i<column;i++){
            for(j=0;j<row/2;j++){
                temp = arr[i][j];
                arr[i][j] = arr[i][row-j-1];
                arr[i][row-j-1] = temp;
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 03:42

    This a better version of it in Java: I've made it for a matrix with a different width and height

    • h is here the height of the matrix after rotating
    • w is here the width of the matrix after rotating

     

    public int[][] rotateMatrixRight(int[][] matrix)
    {
        /* W and H are already swapped */
        int w = matrix.length;
        int h = matrix[0].length;
        int[][] ret = new int[h][w];
        for (int i = 0; i < h; ++i) {
            for (int j = 0; j < w; ++j) {
                ret[i][j] = matrix[w - j - 1][i];
            }
        }
        return ret;
    }
    
    
    public int[][] rotateMatrixLeft(int[][] matrix)
    {
        /* W and H are already swapped */
        int w = matrix.length;
        int h = matrix[0].length;   
        int[][] ret = new int[h][w];
        for (int i = 0; i < h; ++i) {
            for (int j = 0; j < w; ++j) {
                ret[i][j] = matrix[j][h - i - 1];
            }
        }
        return ret;
    }
    

    This code is based on Nick Berardi's post.

    0 讨论(0)
  • 2020-11-22 03:43

    There are tons of good code here but I just want to show what's going on geometrically so you can understand the code logic a little better. Here is how I would approach this.

    first of all, do not confuse this with transposition which is very easy..

    the basica idea is to treat it as layers and we rotate one layer at a time..

    say we have a 4x4

    1   2   3   4
    5   6   7   8
    9   10  11  12
    13  14  15  16
    

    after we rotate it clockwise by 90 we get

    13  9   5   1
    14  10  6   2   
    15  11  7   3
    16  12  8   4
    

    so let's decompose this, first we rotate the 4 corners essentially

    1           4
    
    
    13          16
    

    then we rotate the following diamond which is sort of askew

        2
                8
    9       
            15
    

    and then the 2nd skewed diamond

            3
    5           
                12
        14
    

    so that takes care of the outer edge so essentially we do that one shell at a time until

    finally the middle square (or if it's odd just the final element which does not move)

    6   7
    10  11
    

    so now let's figure out the indices of each layer, assume we always work with the outermost layer, we are doing

    [0,0] -> [0,n-1], [0,n-1] -> [n-1,n-1], [n-1,n-1] -> [n-1,0], and [n-1,0] -> [0,0]
    [0,1] -> [1,n-1], [1,n-2] -> [n-1,n-2], [n-1,n-2] -> [n-2,0], and [n-2,0] -> [0,1]
    [0,2] -> [2,n-2], [2,n-2] -> [n-1,n-3], [n-1,n-3] -> [n-3,0], and [n-3,0] -> [0,2]
    

    so on and so on until we are halfway through the edge

    so in general the pattern is

    [0,i] -> [i,n-i], [i,n-i] -> [n-1,n-(i+1)], [n-1,n-(i+1)] -> [n-(i+1),0], and [n-(i+1),0] to [0,i]
    
    0 讨论(0)
  • 2020-11-22 03:44

    Time - O(N), Space - O(1)

    public void rotate(int[][] matrix) {
        int n = matrix.length;
        for (int i = 0; i < n / 2; i++) {
            int last = n - 1 - i;
            for (int j = i; j < last; j++) {
                int top = matrix[i][j];
                matrix[i][j] = matrix[last - j][i];
                matrix[last - j][i] = matrix[last][last - j];
                matrix[last][last - j] = matrix[j][last];
                matrix[j][last] = top;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题