上图是题目描述来源LeetCode
我的第一种解法是 将所给二维数组由外向内分成n/2上取整层
然后逐层各元素顺时针移动90度
举个例子
最外层像这样移动,那么当完成对倒数第二个元素的移动时该层的旋转也就完成了 那上面的例子来说就是在第一层完成对2的移动时就已经完成了最外层的旋转,再往里只有一个元素,不用旋转。
时间复杂度分析
(n-1)*4+(n-3)**4+…+1 = O(n^2)
算法实现
class Solution {
public void rotate(int[][] matrix) {
int len = matrix.length;
for(int i = 0;;i++)
{
int j = i;
int last = i+len-1;
int start = i;
for(;j<i+len-1;j++)
{
int temp = 0;
int time = 0;
while(time < 4)
{
int ai,aj;
if(time == 0)
{
aj = last;
ai = i+((j+len-1)%last);
temp = matrix[ai][aj];
matrix[ai][aj] = matrix[i][j];
i = ai;
j = aj;
time++;
}
if(time == 1)
{
aj = j - ((i+len-1)%last);
ai = last ;
temp = matrix[ai][aj]^temp;
matrix[ai][aj] = matrix[ai][aj]^temp;
temp = matrix[ai][aj]^temp;
i = ai;
j = aj;
time++;
}
if(time == 2)
{
aj = start;
ai = j;
temp = matrix[ai][aj]^temp;
matrix[ai][aj] = matrix[ai][aj]^temp;
temp = matrix[ai][aj]^temp;
i = ai;
j = aj;
time++;
}
if(time == 3)
{
ai = last - len + 1;
aj = j - ((i - len +1)-start);
temp = matrix[ai][aj]^temp;
matrix[ai][aj] = matrix[ai][aj]^temp;
temp = matrix[ai][aj]^temp;;
j = aj;
i = ai;
time ++;
}
}
}
len -= 2;
if(len <= 1)
{
break;
}
}
}
}
代码量60行左右十分复杂
另一种方法是
矩阵转置加翻转
仔细观察会发现 图像旋转顺时针旋转90度刚好是图像矩阵转置 然后各行数组倒序
代码实现
public void rotate(int[][] matrix) {
for(int i = 0;i<matrix.length;i++)
{
for(int j = i+1;j<matrix.length;j++)
{
matrix[i][j] = matrix[i][j]^matrix[j][i];
matrix[j][i] = matrix[i][j]^matrix[j][i];
matrix[i][j] = matrix[i][j]^matrix[j][i];
}
}//矩阵转置
for(int i = 0;i<matrix.length;i++)
{
for(int j = 0;j<matrix.length/2;j++)
{
matrix[i][j] = matrix[i][j]^matrix[i][matrix.length-1-j];
matrix[i][matrix.length-1-j] = matrix[i][j]^matrix[i][matrix.length-1-j];
matrix[i][j] = matrix[i][j]^matrix[i][matrix.length-1-j];
}
}//倒序
}
时间复杂度
转置 n*(n-1)/2 = O(n^2);
翻转 O(nlog(n))
最后也就是 O(n^2)
简简单单20行
虽然时间复杂度是一样的但是 显然第二种是优解
2 tips
tip1:翻转算法 ,折半对换时间复杂度 就是将一个数组对半分,首尾相替。
tip2:两值互换,常用的是引入一个临时变量,临时存储一个元素的办法。这里用的是异或换值法,省去了临时变量,目的同样是将两值互换。
互换公式 现有两值 a ,b 欲交换a,b ;换法
a = a^b;
b = a^b;
a = a^b;
我算法入门水平,有不对的恳请指出!任何想法欢迎留言。