How do you rotate a two dimensional array?

后端 未结 30 3091
耶瑟儿~
耶瑟儿~ 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:31

    There are a lot of answers already, and I found two claiming O(1) time complexity. The real O(1) algorithm is to leave the array storage untouched, and change how you index its elements. The goal here is that it does not consume additional memory, nor does it require additional time to iterate the data.

    Rotations of 90, -90 and 180 degrees are simple transformations which can be performed as long as you know how many rows and columns are in your 2D array; To rotate any vector by 90 degrees, swap the axes and negate the Y axis. For -90 degree, swap the axes and negate the X axis. For 180 degrees, negate both axes without swapping.

    Further transformations are possible, such as mirroring horizontally and/or vertically by negating the axes independently.

    This can be done through e.g. an accessor method. The examples below are JavaScript functions, but the concepts apply equally to all languages.

     // Get an array element in column/row order
     var getArray2d = function(a, x, y) {
       return a[y][x];
     };
    
     //demo
     var arr = [
       [5, 4, 6],
       [1, 7, 9],
       [-2, 11, 0],
       [8, 21, -3],
       [3, -1, 2]
     ];
    
     var newarr = [];
     arr[0].forEach(() => newarr.push(new Array(arr.length)));
    
     for (var i = 0; i < newarr.length; i++) {
       for (var j = 0; j < newarr[0].length; j++) {
         newarr[i][j] = getArray2d(arr, i, j);
       }
     }
     console.log(newarr);

    // Get an array element rotated 90 degrees clockwise
    function getArray2dCW(a, x, y) {
      var t = x;
      x = y;
      y = a.length - t - 1;
      return a[y][x];
    }
    
    //demo
    var arr = [
      [5, 4, 6],
      [1, 7, 9],
      [-2, 11, 0],
      [8, 21, -3],
      [3, -1, 2]
    ];
    
    var newarr = [];
    arr[0].forEach(() => newarr.push(new Array(arr.length)));
    
    for (var i = 0; i < newarr[0].length; i++) {
      for (var j = 0; j < newarr.length; j++) {
        newarr[j][i] = getArray2dCW(arr, i, j);
      }
    }
    console.log(newarr);

    // Get an array element rotated 90 degrees counter-clockwise
    function getArray2dCCW(a, x, y) {
      var t = x;
      x = a[0].length - y - 1;
      y = t;
      return a[y][x];
    }
    
    //demo
    var arr = [
      [5, 4, 6],
      [1, 7, 9],
      [-2, 11, 0],
      [8, 21, -3],
      [3, -1, 2]
    ];
    
    var newarr = [];
    arr[0].forEach(() => newarr.push(new Array(arr.length)));
    
    for (var i = 0; i < newarr[0].length; i++) {
      for (var j = 0; j < newarr.length; j++) {
        newarr[j][i] = getArray2dCCW(arr, i, j);
      }
    }
    console.log(newarr);

    // Get an array element rotated 180 degrees
    function getArray2d180(a, x, y) {
      x = a[0].length - x - 1;
      y = a.length - y - 1;
      return a[y][x];
    }
    
    //demo
    var arr = [
      [5, 4, 6],
      [1, 7, 9],
      [-2, 11, 0],
      [8, 21, -3],
      [3, -1, 2]
    ];
    
    var newarr = [];
    arr.forEach(() => newarr.push(new Array(arr[0].length)));
    
    for (var i = 0; i < newarr[0].length; i++) {
      for (var j = 0; j < newarr.length; j++) {
        newarr[j][i] = getArray2d180(arr, i, j);
      }
    }
    console.log(newarr);

    This code assumes an array of nested arrays, where each inner array is a row.

    The method allows you to read (or write) elements (even in random order) as if the array has been rotated or transformed. Now just pick the right function to call, probably by reference, and away you go!

    The concept can be extended to apply transformations additively (and non-destructively) through the accessor methods. Including arbitrary angle rotations and scaling.

提交回复
热议问题