今天是2020年4月7日,每日一题的第三天。
题目描述
给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。不占用额外内存空间能否做到?
示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
实例 2:
给定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],
原地旋转输入矩阵,使其变为:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]
题目分析
通过观察可以发现,在旋转90度后,第一行数据旋转后变成了最右边的一列,第二行数据变成了右面的倒数第二列数据。
开辟新的空间保存原数据,按每一行来处理,放置到对应的列。或者原地进行旋转,以对角线进行左右、上下旋转,完成后在对每一行,以中点为界限,左右翻转完成旋转工作。
题目代码
- 开辟新的存储空间
/**
* 第一行将放在最后一列,第二行放在倒数第二列。按行和按列来进行处理
* 时间复杂度:O(N^2)
* 空间复杂度:O(N^2)
* N为matrix的边长
*
* @param matrix
*/
public void rotate(int[][] matrix) {
int[][] copyMatrix = new int[matrix.length][matrix[0].length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
copyMatrix[i][j] = matrix[i][j];
}
}
// 第一行经过运算后,称为最右面的一列。以此类推
for (int i = 0; i < copyMatrix.length; i++) {
for (int j = 0; j < copyMatrix[0].length; j++) {
matrix[j][copyMatrix[0].length - 1 - i] = copyMatrix[i][j];
}
}
}
- 原地旋转
/**
* 原地旋转
* 先由对角线进行翻转,再按每一行的中点进行翻转
*
* @param matrix
*/
public void rotate2(int[][] matrix) {
int length = matrix.length;
// 先以对角线(左上-右下)为轴进行翻转。最后一行不需要处理,最后一行对角线元素右侧没有其他元素。
for (int i = 0; i < length - 1; i++) {
for (int j = i + 1; j < length; j++) {
int tmp = matrix[j][i];
matrix[j][i] = matrix[i][j];
matrix[i][j] = tmp;
}
}
// 再对每一行以中点进行翻转
int middle = length >> 1;
for (int i = 0; i < length; i++) {
for (int j = 0; j < middle; j++) {
int tmp = matrix[i][j];
matrix[i][j] = matrix[i][length - 1 - j];
matrix[i][length - 1 - j] = tmp;
}
}
}
原地旋转的方法参考了甜姐的题解,感谢甜姐,题解地址:https://leetcode-cn.com/problems/rotate-matrix-lcci/solution/jian-dan-java-yuan-di-shuang-bai-by-sweetiee/