给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
题目地址:https://leetcode.cn/problems/rotate-image
作者:本人
刚拿到这题,看到“原地”就不敢动了,只想着谁和谁交换,想了一会儿想不出来。
观察示例1,发现了规律:输入【【1,2,3】,【4,5,6】,【7,8,9】】
只需要输出【【7,4,1】,【8,5,2】,【9,6,3】】即可
输出的二维数组的第一个一维数组的元素 取自 输入的二维数组的每个一维数组的第一个元素,依次循环取即可,也就是“外层(二维数组)从后往前遍历,内层(一维数组)从前往后遍历”
我现将输入数组的全素按上面的规律取出来放到一个数组中存储,再赋值给这个数组,因为题目要求原地,所以最后题目要检查的数组就是matrix数组
class Solution {
public void rotate(int[][] matrix) {
int len = matrix.length;
int arr[] = new int[len*len];
int temp = 0;
//将二维数组按规律存储到arr[]中
for (int j = 0; j < len; j++) {
for (int i = len - 1; i >= 0; i--) {
arr[temp] = matrix[i][j];
temp++;
}
}
temp = 0;
//再循环赋值给matrix
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
matrix[i][j] = arr[temp];
temp++;
}
}
}
}
效果
可能我的方法时投机取巧吧,因为题目说了原地,但我还是建立了一个存储的数组,但通过还是能通过,如果这个方法真的可以算一种合理的解法,那这道题的难度我觉得应该是“简单”,而不是“中等” ,但我看力扣官方题解竟然也有类似解法,emm......
所以推荐读者看下面的解法,真正做到了“原地”。
作者:本人
思路:
观察示例1我们能得出规律
原数组长这样
1 2 3
4 5 6
7 8 9
左右翻转之后长这样
3 2 1
6 5 4
9 8 7
对角线翻转之后长这样
7 4 1
8 5 2
9 6 3
所以我们的方法就是
1.先二维数组左右翻转
2.再沿 左下到右上的 对角线翻转
思路非常简单,但代码不好写
先写一个交换的代码
//将arr[a] 与 brr[b] 交换
private void swap(int[] arr, int a,int[] brr , int b) {
int temp = arr[a];
arr[a] = brr[b];
brr[b] = temp;
}
左右翻转
1. 交换第一个数组的 最左边元素 和 最右边元素
2. 交换第一个数组的 左边第二个元素 和 右边第二个元素
3. 循环交换到 左边>=右边
4. 开始交换 第二个数组的最左边元素 和 最右边元素
5. 循环交换到 左边>=右边
6.开始交换 第三个数组的最左边元素 和 最右边元素
7. 循环交换到 左边>=右边
//左右翻转
for (int i = 0; i < len; i++) {
int left = 0;
int right = len-1;
while (left < right){
swap(matrix[i] ,left ,matrix[i] ,right);
left++;
right--;
}
}
左下到右上的对角线翻转
先定义tempI 和 tempJ,指向左下角的元素
交换对应颜色的数组
将两个指针沿对角线移动,再交换对应颜色的元素
最后,两指针移动到对角线顶部就交换完毕了
注意
思路虽然简单,但自己写代码就需要多思考,建议自己写一写这一块
//沿 左下到右上 对角线翻转
int tempI = len-1;
int tempJ = 0;
while (tempI > 0){
int i = tempI;
int j = tempJ;
while (i > 0){
swap(matrix[i-1],tempJ,matrix[tempI], j+1);
i--;
j++;
}
tempI--;
tempJ++;
}
完整代码
/**
* 两次翻转法:
* 1.先左右翻转
* 2.再沿 左下到右上的 对角线翻转
*/
class Solution {
public void rotate(int[][] matrix) {
int len = matrix.length;
//左右翻转
for (int i = 0; i < len; i++) {
int left = 0;
int right = len-1;
while (left < right){
swap(matrix[i] ,left ,matrix[i] ,right);
left++;
right--;
}
}
//沿 左下到右上 对角线翻转
int tempI = len-1;
int tempJ = 0;
while (tempI > 0){
int i = tempI;
int j = tempJ;
while (i > 0){
swap(matrix[i-1],tempJ,matrix[tempI], j+1);
i--;
j++;
}
tempI--;
tempJ++;
}
}
//将arr[a] 与 brr[b] 交换
private void swap(int[] arr, int a,int[] brr , int b) {
int temp = arr[a];
arr[a] = brr[b];
brr[b] = temp;
}
}
效果
这个方法可能更符合出题人的想法,真正的是原地修改。