题目描述
给定一个 n × n 的二维矩阵 matrix
表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[[7,4,1],[8,5,2],[9,6,3]]
思路提示
方法一:原地计算
将每个位置旋转到对应位置,如下:
从中可以看出,每次轮回需要涉及四次交换,为避免覆盖原值,需要先将原值存入临时变量。如先将(0,0)的值存入temp,再用(3,0)替换(0,0),(3,3)替换(3,0),(0,3)替换(3,0),最后temp替换(0,3)。下一轮是(2,0)->(0,1),(3,2)->(2,0),(1,3)->(3,2),temp -> (0,1)。由此类推,可知
- 第 i 行 j 列的元素matrix(i,j)被第 i 列的元素替代,第 i 列的元素的行号与被替换的元素的列号 j 之和刚好为矩阵长度length-1,设为 m = length - 1 - j。
- 第 m 行 i 列的元素matrix(m,i)被第 m 列的元素替代,第 m 列的元素的行号与被替换的列号 i 之和为length - 1,设为 n = length - 1 - i。
- 第 n 行 m 列的元素matrix(n,m)被第 n 列的元素替代,第 n 列的元素的行号刚好为元素matrix(i,j)的列号 j 。
- j方向总是从i开始进行到length-1-i的时候跳出,即进入下一个圈。
代码实现
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int length = matrix.size();
//因为是对称的,只需要计算循环前半行即可
for (int i = 0; i < length / 2; i++)
for (int j = i; j < length - i - 1; j++) {//外圈旋转完毕,内圈开始旋转
int temp = matrix[i][j];
int m = length - j - 1;
int n = length - i - 1;
matrix[i][j] = matrix[m][i];
matrix[m][i] = matrix[n][m];
matrix[n][m] = matrix[j][n];
matrix[j][n] = temp;
}
}
};
方法二:翻转代替旋转
我们还可以另辟蹊径,用翻转操作代替旋转操作。我们还是以题目中的示例二
作为例子,先将其通过水平轴翻转得到:
再根据主对角线翻转得到:
就得到了答案。这是为什么呢?对于水平轴翻转而言,我们只需要枚举矩阵上半部分的元素,和下半部分的元素进行交换,即
对于主对角线翻转而言,我们只需要枚举对角线左侧的元素,和右侧的元素进行交换,即
将它们联立即可得到:
即可得到翻转后的位置。
代码实现
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n=matrix.size();
for(int i=0;i<n/2;++i){//上下对称,只需交换一半,如果全部遍历就会恢复为原数组
for(int j=0;j<n;++j){
int temp = matrix[i][j];
matrix[i][j] = matrix[n-i-1][j];
matrix[n-i-1][j] = temp;
}
}
// for(int i=0;i<n;++i){
// for(int j=0;j<i;++j){//从(i,j)交换到(i-1,i-1),即遍历左下角一半的数组
// int temp = matrix[i][j];
// matrix[i][j] = matrix[j][i];
// matrix[j][i] = temp;
// }
// }
for(int i=0;i<n-1;++i){
for(int j=i+1;j<n;++j){//遍历右上角的数组
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
}
};
通过试验发现,采用交换函数swap, swap(matrix[i][j],matrix[n-i-1][j]);由于时间太短看不出提升,内存反而多了一丢丢。
一般情况下,使用swap
函数比手动编写赋值代码更快。swap
函数是C++标准库中提供的函数,它使用了优化的实现方式,能够高效地交换两个对象的值。相比之下,手动编写的赋值代码可能需要更多的指令和操作来完成交换过程,因此通常会更慢。