题目
贪心
题目很有意思,不能使用新的矩阵来存储结果,只能在原数组上进行操作,考虑到矩阵的维度,那么必然有某种规律。
首先假设只能用一个 temp 来存储矩阵中的某个元素,那么一共需要连续进行四次赋值操作才能实现一个循环,以四维矩阵为例,一次循环操作流程如下:
temp = matrix[0][0];
matrix[0][0] = matrix[3][0];
matrix[3][0] = matrix[3][3];
matrix[3][3] = matrix[0][3];
matrix[0][3] = temp;
既然完成了一个循环,那么我们来探索一下其中的奥妙:
-
- 将元素的起始点记录下来:
sx = 0; sy = 0;
- 将元素的起始点记录下来:
-
- 用两个变量记录目标元素的位置:
tx = 3; ty = 0;
- 用两个变量记录目标元素的位置:
-
- 下一个元素的位置即为:
x = sx + tx; y = sy + ty;
- 下一个元素的位置即为:
-
- 考虑下一步的位置,首先对起始点位置更新:
sx = sx + tx; sy = sy + ty;
- 考虑下一步的位置,首先对起始点位置更新:
-
- 根据猜测的规律,对移动变量进行更新:
swap(tx, ty); tx = -tx;
- 根据猜测的规律,对移动变量进行更新:
-
- 下一个元素的位置即为:
x = sx + tx; sy = sy + ty;
- 下一个元素的位置即为:
通过验证,发现第一个元素的旋转确实满足上述规律,考虑到每四次操作达成一个循环,因此四次操作后就回到了最开始的点:sx = 0; sy = 0;
。
那么开始考虑其他位置:
-
- 使起始点右移一位:
sy = sy + 1;
- 使起始点右移一位:
-
- 跑一边上面的旋转流程,发现满足规律;
-
- 起始点继续右移,直到:
sy = n - 1;
结束;
- 起始点继续右移,直到:
我们可以发现,上一步结束后,成功对矩阵的最外圈完成旋转,该步骤可以称为一次“旋转”。
既然能完成最外圈,那么也能对内圈进行同样的操作,只不过此时的起始点变为了:sx = 1; sy = 1;
,矩阵的维度也变成了:n = n - 2;
根据规律可以发现,只要完成 n / 2
次“旋转”,就可以完成整个矩阵的旋转操作。
class Solution {
public:
void rotates(vector<vector<int>>& matrix, int sx, int sy, int sn) { // 一次“旋转”操作
int tx = sn - 1, ty = 0;
for(int i = 1; i < sn; ++i) {
int temp = matrix[sx][sy];
matrix[sx][sy] = matrix[sx + tx][sy + ty];
sx = sx + tx; sy = sy + ty;
swap(tx, ty); tx = -tx;
matrix[sx][sy] = matrix[sx + tx][sy + ty];
sx = sx + tx; sy = sy + ty;
swap(tx, ty); tx = -tx;
matrix[sx][sy] = matrix[sx + tx][sy + ty];
sx = sx + tx; sy = sy + ty;
swap(tx, ty); tx = -tx;
matrix[sx][sy] = temp;
sx = sx + tx; sy = sy + ty;
swap(tx, ty); tx = -tx;
sy++; tx--; ty--;
}
}
void rotate(vector<vector<int>>& matrix) {
int flag = matrix.size(); // 记录矩阵维度变化
for(int i = 0; i < matrix.size() / 2; ++i) {
rotates(matrix, i, i, flag);
flag-=2;
}
}
};
二次对称法
观察可以发现,旋转操作实际上就是对称操作的集合:
- 按 y 轴对称;
- 按副对角线对称。
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
int mid = n / 2;
for(int i = 0; i < n; ++i)
for(int j = 0; j < mid; ++j)
swap(matrix[i][j], matrix[i][n - j - 1]);
for(int i = 0; i < n; ++i)
for(int j = 0; j < n - i - 1; ++j)
swap(matrix[i][j], matrix[n - j - 1][n - i - 1]);
}
};