LC Rotate Image

48. Rotate Image

Difficulty: Medium

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Note:

You have to rotate the image , which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.

Example 1:

Given input matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

rotate the input matrix in-place such that it becomes:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

Example 2:

Given input matrix =
[
  [ 5, 1, 9,11],
  [ 2, 4, 8,10],
  [13, 3, 6, 7],
  [15,14,12,16]
], 

rotate the input matrix in-place such that it becomes:
[
  [15,13, 2, 5],
  [14, 3, 4, 1],
  [12, 6, 8, 9],
  [16, 7,10,11]
]

解题思路

解题先从简单的case来想,如果n = 1的话,我们不需要移动
如果n = 2的话,矩阵的转变如下
1 2 => 3 1
3 4 => 4 2
我们想要知道的不是1从原本的m[0][0]去到了哪个新的位置(无论是去了m[0][1]好,m[1][1]也好),而是要知道后上位的坐标原本在哪个位置才能推断出规律(我觉得是懂了此理的话,解法同样适用于180度,270度,etc)
1的位置的坐标m[0][0] = m[1][0]新上位的数字的旧坐标
m[0][1] = m[0][0]
m[1][0] = m[1][1]
m[1][1] = m[0][1]
可得出的规律是m[i][j] = m[n - 1 - j][i]
继续在n = 3,4,5也能验证这个规律的真实性
在这里可以得出解法1

但是解法1在空间上并不能满足我们,如果我们想要in-place更改的话,我们需要一次更改四个坐标,这里可以用一个temp变量
已知m[i][j] = m[n - 1 - j][i]
所以四个角的坐标如下
m[i][j]
m[n - 1 - j][i]
m[n - 1 - i][n - 1 - j] (以前我到这里就看不懂为什么了,找了很多博客也不明白,后来挣扎了一会儿才知道这里的i和j其实全就是按照那个规律来plug in而已- -)
m[n - 1 - (n - 1 - j)][n - 1 - i] = m[j][n - 1 -i]

当我们知道四个角的坐标之后我们还需要知道每次要移动的坐标,不像解法1可以直接全部过一遍,一开始我也是完全不知道博客大神们在讲什么,所以从n = 1开始写了起来
n = 1,不需要移动
n = 2,移动m[0][0]
n = 3,移动m[0][0], m[0][1]
n = 4,移动m[0][0], m[0][1], m[0][2], m[1][1]
n = 5,移动m[0][0], m[0][1], m[0][2], m[0][3], m[1][1], m[1][2]
n = 6,移动m[0][0], m[0][1], m[0][2], m[0][3], m[0][4], m[1][1], m[1][2], m[1][3], m[2][2]
(是的我比较愚笨所以不把规律写全一些怕漏掉信息。。)
从这个规律上可见i < n / 2
而j最多也只是会去到n - 1 - i(i <= j < n - 1 - i),这里的i可以认为是每一次一圈正方形的外层的偏离量。比如第一个大圈的偏离量是0,0,所以i是0。下一个小圈的偏离量是在1, 1,所以i是1。每次走圈圈的时候,j必定不会比n - 1 - i大,因为i每次都在增大,而j不可能在小圈的时候走回到大圈
下图是我的解法2的走路规律
拙计图请笑纳
由此可得解法2

Solution

Language: Java

class 解法1 {
	// Time: O(n^2)
	// Space: O(n^2)
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        int[][] m = new int[n][n];
        for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				m[i][j] = matrix[n - 1 - j][i];
			}
		}
        for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				matrix[i][j] = m[i][j];
			}
		}
    }
}
class 解法2 {
	// Time: O(n^2)
	// Space: O(1)
    public void rotate(int[][] matrix) {
        int n = m.length;
        for (int i = 0; i < n / 2; i++) {
            for (int j = i; j < n - 1 - i; j++) {
                int temp = m[i][j];
                m[i][j] = m[n - 1 - j][i];
                m[n - 1 - j][i] = m[n - 1 - i][n - 1 - j];
                 m[n - 1 - i][n - 1 -j] = m[j][n - 1 - i];
                m[j][n - 1 - i] = temp;
            } 
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值