48. 旋转图像
这题一开始我不会写,我以为会用到线性代数(其实并没有)。我看了下题解,发现题解讲的我莫名其妙,只能说看不懂吧。唯一我能看懂的思路是(作者:数据结构和算法)这样的。
因此将一个n维矩阵划分成n/2圈。一圈一圈的旋转。在每一圈中,每一个元素旋转,其实要同时旋转四个(分别是上下左右的元素),因为只旋转90度(360/90=4)。因此,只要第一层的元素都旋转了,那么这一圈就旋转过来了。然后在进行下一圈的旋转。那么在一圈中,其实只要旋转5,1,9这三个元素及其所对应的四个元素。假设这一圈最左上角的元素为Ai,j(i=j),那么只要将Ai,i、Ai,i+1、...Ai,n-i旋转即可。(此时矩阵是从1,1开始,实际上在计算机中是从0开始)。
每一圈的元素其实有个特点,这些元素行下标或者列下标必然是等于这一圈第一列和最后一列的下标。我们其实可以找到每行元素旋转后的规律。(这个规律好像和矩阵存储无关)
假设每一圈第一列和最后一列的下标分别为m,n
1、若i=m;则旋转后的元素为Aj,n
2、若i=n;则旋转后的元素为Aj,m
3、若j=m;则旋转后的元素为An,i
4、若j=m;则旋转后的元素为An,i
对于n维数组,从0->n-1,
只要每一圈处理最上层的元素总数减一的元素,那么这一圈就能遍历完。对于第i圈(从外到内),要处理i,i+1,...n-i-2个元素。对于每一个元素,要同时处理四个元素,分别是上、下、左、右四个位置。
那么要处理多少圈呢?由于圈数是对称的,那么要处理0,1,...(n-1)/2圈。
明白了要处理的圈数和每一层要处理的元素个数,那么代码就出来了。
void rotate(int** matrix, int matrixSize, int* matrixColSize) {
for (int i = 0; i < (matrixSize / 2); i++)//对于每一层
{
for (int j = i; j < matrixSize - i - 1; j++)//对于每一层的要改变的节点
{
int temp = matrix[i][j];//零时存放数据,防止数据丢失
int assist1 = matrixSize - i - 1;
int assist2 = matrixSize - j - 1;
matrix[i][j] = matrix[assist2][i];//最左边的旋转
matrix[assist2][i] = matrix[assist1][assist2];//最下面的旋转
matrix[assist1][assist2] = matrix[j][assist1];//最右边的旋转
matrix[j][assist1] = temp;//最上面的旋转
}
}
}