我有一个表示为一维数组的n x n
矩阵。左上角从索引0开始。索引i计算为i = x * n + y
,其中x和y是二维表示形式中的矩阵条目的索引。
对于n = 4
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
要将其顺时针旋转90度,我们得到
12 8 4 0
13 9 5 1
14 10 6 2
15 11 7 3
映射现在为i = 12 + y - (n * x)
使用O(n ^ 2)空间,我们只需将原始索引映射到旋转索引,然后复制到原始位置的条目上。很简单。
但是我想知道是否有一种方法可以对方形矩阵进行一维表示。我知道那里有很好的二维表示算法...有什么建议吗?
答案 0 :(得分:0)
任何旋转都可以分解为横跨两个不同轴的两个连续反射。在您的情况下,可以通过交换矩阵元素来完成反射。因此可以就地完成。
例如,对于旋转90度,可以围绕x轴进行第一次反射,将第一行与最后一行交换,然后将第二行与第三行交换,得到:
12 13 14 15
8 9 10 11
4 5 6 7
0 1 2 3
现在第二次反射围绕主对角线,就像矩阵的转置一样,以对称方式在对角线上交换元素:
12 8 4 0
13 9 5 1
14 10 6 2
15 11 7 3
两个反射都可以迭代交换单个元素来完成,因此它们可以就地完成。矩阵是1D还是2D不会匹配。
就地旋转的C ++示例(矩阵的一维数组表示):
const int ROWS = 4;
const int COLS = ROWS;
int A[ROWS*COLS];
int index(int row, int col) { return col + COLS * row; }
void swap(int i, int j) { int a = A[i]; A[i] = A[j]; A[j] = a; }
// x-axis reflection
for(int row_i = 0 ; row_i < ROWS / 2; ++row_i) {
int row_j = ROWS - row_i - 1;
for(int col_i = 0 ; col_i < COLS ; ++col_i)
swap( index(row_i, col_i), index(row_j, col_i) );
}
// diagonal reflection
for(int row_i = 0 ; row_i < ROWS; ++row_i) {
for(int col_i = row_i + 1 ; col_i < COLS ; ++col_i)
swap( index(row_i, col_i), index(col_i, row_i) );
}