题目:48旋转图像
给定一个 n × n 的二维矩阵 matrix
表示一个图像。请你将图像顺时针旋转 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]]
提示:
n == matrix.length == matrix[i].length
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000
链接:
. - 力扣(LeetCode)
分析:
方法一:数学方法(先转置,再左右翻转)
方法二:分治(分四部分再旋转)
我领悟的思想是:
1、先分成4个部分,再用两层循环遍历这四分之一部分。
2、将左右的顶点拿出来,存在一个临时的temp中,再将更新的数字放进入(后面优化直接将第一个顶点存temp中,后面三个顶点直接填进去。)
3、由于有两层循环,所以这四分之一个部分里的所有的元素都会重复顶点的操作,这大概就是分治
ps:搞了三四个小时都搞不懂这一题,靠,太笨了
参考代码:
package com.atguigu.algorithm.arrays;
public class RotateImage {
//方法一:数学方法(矩阵转置,再翻转每一行(前后对调))
public void rotate1(int[][] matrix) {
int n = matrix.length;
// 1.转置矩阵 双循环,第一层是行,第二层是列(行上具体的点)
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// 2.翻转每一行
for (int i = 0; i < n; i++) {
for (int j = 0; j < n / 2; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[i][n - j - 1];
matrix[i][n - j - 1] = temp;
}
}
}
// 方法二:分治思想,分为四个子矩阵分别考虑
public void rotate2(int[][] matrix) {
int n = matrix.length;
// 遍历四分之一矩阵,左上角
for (int i = 0; i < n / 2 + n % 2; i++) {
for (int j = 0; j < n / 2; j++) {
// 对于matrix[i][j],需要找到不同的四分矩阵中对应的另外三个位置和元素
//定义一个临时数组,保存对应的四个元素
int[] temp = new int[4];
int row = i;
int col = j;
//行列转换的规律: row + newCol = n-1 , col = newRow
for (int k = 0; k < 4; k++) {
temp[k] = matrix[row][col];
int x = row;
row = col;
col = n - 1 - x;
}
// 再次遍历要处理的四个位置,将旋转之后的数据填入
for (int k = 0; k <4; k++) {
// 用上一个值替换当前的位置
matrix[row][col] = temp[(k + 3) % 4];
int x = row;
row = col;
col = n - 1 - x;
}
}
}
}
//方法三:改进
public void rotate3(int[][] matrix) {
int n = matrix.length;
//遍历四分之一矩阵
for (int i = 0; i < (n+1)/2; i++) {
for (int j = 0; j < n / 2; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n - 1 - j][i]; //将上一个位置的元素填入,注意:右边是上一个元素!!!
matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j]; //规律:上一个元素的列变成下一个元素的行
matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i]; //规律:上一个元素的行+下一个元素的列=n-1
matrix[j][n - 1 - i] = temp;
}
}
}
public static void main(String[] args) {
int[][] image1 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
};
int[][] image2 = {
{5, 1, 9, 11},
{2, 4, 8, 10},
{13, 3, 6, 7},
{15, 14, 12, 16}
};
RotateImage rotateImage = new RotateImage();
rotateImage.rotate3(image1);
rotateImage.printImage(image1);
rotateImage.rotate3(image2);
rotateImage.printImage(image2);
}
private void printImage(int[][] image) {
System.out.println("image = " );
for (int[] line : image) {
for (int point : line) {
System.out.print(point+"\t");
}
System.out.println();
}
}
}
复杂度分析:
方法一的复杂度:
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)。旋转操作是原地完成的,只耗费常数空间。
方法二、三的复杂度:
- 时间复杂度:O(N^2) 是两重循环的复杂度。
- 空间复杂度:O(1)