今天看到了这样的一道题目,花了一个小时做了一下,用了两种解法,第二种解法空间复杂度为O(1),但思路比较复杂,大家可以一起来讨论一下~
解法一
对于方阵逆时针旋转,很容易想到的就是找出每一个数的规律,复制多一份额外的空间,然后遍历每一个位置,找出其旋转前的位置。
对于下面的方阵,有n = 3
可以知道旋转后的方阵为
即有下面变换:
(0,0) <= (0,2)
(1,0) <= (0,1)
(2,0) <= (0,0)…
可以抽象出来(i,j)<= (j,n - 1 - i),代码如下:
void matrixS(int a[length][length])
{
show(a);
int b[length][length];
for (size_t i = 0; i < length; i++)
{
for (size_t j = 0; j < length; j++)
{
// 两层for循环,遍历方阵每一个数
b[i][j] = a[j][length - 1 - i];
}
}
printf("旋转后:\n");
show(b);
}
有测试结果如下:
解法二
第一种解法时间复杂度O(n),空间复杂度O(n),效率很低,所以有了第二种解法,思路如下:
对于一个n × n 的方阵a,当 n 为偶数时,其外围方圈的层数为 n / 2 ,当 n 为奇数时,除去中心点上的数无需旋转,即有[n / 2]层方圈,[]表示取整,所以无论 n 为奇数还是偶数,我们只需要遍历 n / 2 层,对每一层进行旋转即可。
而对于方阵的每一层方圈 i ,i 属于 [0,n / 2),可以按照四条边分为四个部分,每一个部分均有 n - i * 2 - 1 个数,比如 3 × 3 的方阵最外层有四个部分,每一部分有3 - 0 - 1 = 2 个数,如图:
可以任取一部分作为基准存储起来,在这里为取第一部分,代码如下:
void matrixS2(int a[length][length])
{
show(a);
// 对每一层
for (size_t i = 0; i < length / 2; i++)
{
// 对每一层的四个部分的每一个数
for (size_t j = 0; j < length - i * 2 - 1; j++)
{
// 存储第一部分
int tmp = a[i + j][i];
// 将第四部分写到第一部分
a[i + j][i] = a[i][length - i - j - 1];
// 将第三部分写到第四部分
a[i][length - i - j - 1] = a[length - i - j - 1][length - 1 - i];
// 将第二部分写到第三部分
a[length - i - j - 1][length - 1 - i] = a[length - 1 - i][j + i];
// 将第一部分写到第四部分
a[length - i - 1][i + j] = tmp;
}
}
printf("旋转后:\n");
show(a);
}
测试结果:
来源:CSDN
作者:Jack_Cheng_
链接:https://blog.csdn.net/Jack_Cheng_/article/details/104798848