受Raymond Chen帖子的启发,假设你有一个4x4二维数组,写一个函数使它旋转90度。Raymond链接到伪代码中的解决方案,但我想看到一些真实的东西。

[1][2][3][4]
[5][6][7][8]
[9][0][1][2]
[3][4][5][6]

就变成:

[3][9][5][1]
[4][0][6][2]
[5][1][7][3]
[6][2][8][4]

更新:Nick的答案是最直接的,但是有没有比n²更好的方法呢?如果矩阵是10000x10000呢?


当前回答

在JavaScript中实现dimple的+90伪代码(例如转置然后反转每一行):

function rotate90(a){
  // transpose from http://www.codesuck.com/2012/02/transpose-javascript-array-in-one-line.html
  a = Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
  // row reverse
  for (i in a){
    a[i] = a[i].reverse();
  }
  return a;
}

其他回答

/* 90-degree clockwise:
   temp_array         = left_col
   left_col           = bottom_row
   bottom_row         = reverse(right_col)
   reverse(right_col) = reverse(top_row)
   reverse(top_row)   = temp_array
*/
void RotateClockwise90(int ** arr, int lo, int hi) {

  if (lo >= hi) 
    return;

  for (int i=lo; i<hi; i++) {
    int j = lo+hi-i;
    int temp   = arr[i][lo];
    arr[i][lo] = arr[hi][i];
    arr[hi][i] = arr[j][hi];
    arr[j][hi] = arr[lo][j];
    arr[lo][j] = temp;
  }

  RotateClockwise90(arr, lo+1, hi-1);
}

下面是一个c#静态泛型方法,它可以为您完成这项工作。变量的名称很好,所以您可以很容易地理解算法的思想。

private static T[,] Rotate180 <T> (T[,] matrix)
{
    var height = matrix.GetLength (0);
    var width = matrix.GetLength (1);
    var answer = new T[height, width];

    for (int y = 0; y < height / 2; y++)
    {
        int topY = y;
        int bottomY = height - 1 - y;
        for (int topX = 0; topX < width; topX++)
        {
            var bottomX = width - topX - 1;
            answer[topY, topX] = matrix[bottomY, bottomX];
            answer[bottomY, bottomX] = matrix[topY, topX];
        }
    }

    if (height % 2 == 0)
        return answer;

    var centerY = height / 2;
    for (int leftX = 0; leftX < Mathf.CeilToInt(width / 2f); leftX++)
    {
        var rightX = width - 1 - leftX;
        answer[centerY, leftX] = matrix[centerY, rightX];
        answer[centerY, rightX] = matrix[centerY, leftX];
    }

    return answer;
}

这是一个Javascript解决方案:

const transpose = m => m[0].map((x,i) => m.map(x => x[i]));

a: // original matrix
123
456
789

transpose(a).reverse(); // rotate 90 degrees counter clockwise 
369
258
147

transpose(a.slice().reverse()); // rotate 90 degrees clockwise 
741
852
963

transpose(transpose(a.slice().reverse()).slice().reverse())
// rotate 180 degrees 
987
654
321
short normal[4][4] = {{8,4,7,5},{3,4,5,7},{9,5,5,6},{3,3,3,3}};

short rotated[4][4];

for (int r = 0; r < 4; ++r)
{
  for (int c = 0; c < 4; ++c)
  {
    rotated[r][c] = normal[c][3-r];
  }
}

简单的c++方法,尽管在大数组中会有很大的内存开销。

#转置是Ruby的Array类的标准方法,因此:

% irb
irb(main):001:0> m = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 0, 1, 2], [3, 4, 5, 6]]
=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 0, 1, 2], [3, 4, 5, 6]] 
irb(main):002:0> m.reverse.transpose
=> [[3, 9, 5, 1], [4, 0, 6, 2], [5, 1, 7, 3], [6, 2, 8, 4]]

实现是一个用c写的n^2转置函数,你可以在这里看到: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-transpose 通过选择“点击切换源”旁边的“转置”。

我记得比O(n^2)的解更好,但只适用于特殊构造的矩阵(如稀疏矩阵)