解题思路
这是一道找规律题,下面介绍一下解题思路:
元素位置交换的规律
** 顺时针旋转矩阵,矩阵里面的元素位置交换有如下规律:**
绿色线的那一层
- 绿色线的那一层,以(0,0)为起点。各个元素的起点,和终点如下所示:
起点 ---> 终点
(0,0) ---> (0, 2)
(0,2) ---> (2, 2)
(2,2) ---> (2, 0)
(2, 0) ---> (0, 0)
蓝色线那一层
- 蓝色线那一层,以(0, 1)为起点,各个元素的起点,和终点如下所示:
起点 ---> 终点
(0,1) ---> (1, 2)
(1,2) ---> (2, 1)
(2,1) ---> (1, 0)
(1, 0) ---> (0, 1)
抽象两层交换涉及的4个元素下标
两层交换涉及的4个元素下标,可以抽象为:
用Python 写出伪代码:
set n = matrix.length
i in range(n // 2):
j in range(i, n -i -1):
即,第一层绿色线循环,起点坐标 i = 0 j = 0
起点 ---> 终点
(0,0) ---> (0, 2)
(0,2) ---> (2, 2)
(2,2) ---> (2, 0)
(2, 0) ---> (0, 0)
第二层蓝色线循环,起点坐标 i = 0 j = 1
起点 ---> 终点
(0,1) ---> (1, 2)
(1,2) ---> (2, 1)
(2,1) ---> (1, 0)
(1, 0) ---> (0, 1)
两层循环交换,可以抽象为如下表达
(i, j) -> (j, n- i - 1)
(j, n - i - 1) -> ( n-i -1, n - j -1)
(n -i -1, n -j -1) -> (n - j -1, i)
(n - j -1, i) -> (i, j)
即,总共有四个元素要交换位置(左边,和右边 各出现一次) (i, j), (j, n - i - 1), (n -i -1, n -j -1), (n - j -1, i)
每个要更新元素的下标,和要放到该位置元素的下标
上面是找到要更新元素的下标,即 (i, j), (j, n - i - 1), (n -i -1, n -j -1), (n - j -1, i)
接下来,要找到每个要更新元素,和要放到该位置元素的下标 (i, j) = ? (j, n - i - 1) = ? (n -i -1, n -j -1) = ? (n - j -1, i) = ?
第一层绿色线循环,起点坐标 i = 0 j = 0
即将被更新的下标 ---> 即将放到该位置的,新元素的原始下标
(0,0) = (2, 0)
(0,2) = (0, 0)
(2,2) = (0, 2)
(2, 0) = (2, 2)
第二层蓝色线循环,起点坐标 i = 0 j = 1
即将被更新的下标 ---> 即将放到该位置的,新元素的原始下标
(0, 1) = (1, 0)
(1, 2) = (0, 1)
(2, 1) = (1, 2)
(1, 0) = (2, 1)
两层循环交换 被更新下标, 和即将访道该位置的,新元素的原始下标,可以抽象为如下表达
**注意: 等式右边的(i, j),各自以起始点为值:即,
-
第一层绿线涉及的元素是相对的(i, j)取值始终是(0, 0)
-
第二层蓝线涉及的元素是相对的(i, j)取值始终是(0, 1) **
(i, j) = (n - j - 1, i): e.g. (0,0) = (2, 0) (0,1) = (1, 0) (n- j - 1, i) = (n - i - 1, n - j - i): e.g. (2, 0) = (2, 2) (1, 0)= (2, 1) (n- i - 1, n- j - i) = (i, n - j - 1): e.g. (2, 2) = (0, 2) (2,1) = (1, 2) (i, n - j - 1) = (i, j): e.g. (0,2) = (0, 0) 1, 2) = (0, 1)
所以,用两层for 循环,来实现以两个起点(0,0)和(0,1),实现交换要第一层要,绿色线涉及的元素;和第二层,蓝色线设计的元素 以下是Python实现 示例,
n = len(matrix)
matrix = [[1,2,3],[4,5,6],[7,8,9]]
for i in range(n//2):
for j in range(i, n-i-1):
matrix[i][j],matrix[j][n-1-i],matrix[n-1-i][n-1-j],matrix[n-1-j】[i]
=
matrix[n-1-j][i],matrix[i][j],matrix[j][n-1-i],matrix[n-1-i][n-1-j]
刚开始,我写成了,
matrix[i][j],matrix[j][n-i-1],matrix[n-i-1][n-j-1],matrix[n-j-1][i]=
matrix[j][n-i-1],matrix[n-i-1][n-j-1],matrix[n-j-1][i],matrix[i][j]
就是没有理解 (i,j) 上的元素是旋转后,到了(j,n - i - 1); (j,n - i - 1)上的元素是旋转后,到了 (n - i - 1, n - j -1); .... 而不是,(i,j) 上的元素 = (j,n - i - 1)上的元素;
每次交换4个元素
每次交换4个元素的解决思路,也适用于其他高度的二维矩阵。
如何找到所有 子正方形的起点?###
(即上图中各个小正方形的起点)
以上图为例,矩阵长度为 4
java 代码,如何遍历 每次交换4个元素
int n = matrix.length;
for (int i=0; i<n/2; i++){
for (int j=i; j < n-i-1; j++){
n为矩阵长度 = 4; 最外层for 循环 i = 0, i < n/2 = 2: j = 0, j < n-i-1 = 3 => (i,j)可取值为:(0,0), (0,1), (0,2) 最外层for 循环 i = 1, i < n/2 = 2: j = 1, j < n-i-1 = 2 => (i,j)可取值为:(1,1)
- ( 这些就是 可以用来每次交换4个矩阵元素,所形成正方形的起点)*
交换元素位置时的小技巧:
如果交换元素时,也按照上图中,顺时针依次交换, 那就需要在每次替换掉旧位置上的元素之前,先把该位置上的值保存起来,以便下替换掉下一个元素使用;
这样,每交换4个元素,就需要创建3个临时变量,来保存即将替换掉位置上的元素。
即,如上图那样顺时针交换元素 Step1. temp_1 = matrix[0][0] matrix[0][0] = matrix[3][0]
Step2. temp_2 = matrix[0][3] matrix[0][3] = temp_1
Step3. temp_3 = matrix[3][3] matrix[3][3] = temp_2
Step4.
matrix[3][0] = temp_3
如果,逆时针交换元素,就只需要保存一个临时变量,即 temp_1 = 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_1
其实,总结起来 就是“先使用(该位置的值),后更新(该位置的值)”
Java 代码 实现4个元素交换位置
// 等式左边公式里的i, j 是该次4元素交换的起点值,即 (0,0),(0,1),(0,2)或(1,1)
int temp_i_j = matrix[i][j];
//[0][0] = [3][0]
//[0][1] = [2][0]
matrix[i][j] = matrix[n-j-1][i];
// [3][0] = [3][3]
// [2][0] = [3][2]
matrix[n-j-1][i] = matrix[n-i-1][n-j-1];
// [3][3] = [0][3]
// [3][2] = [1][3]
matrix[n-i-1][n-j-1] = matrix[j][n-i-1];
// [0][3] = [0][0]
// [1][3] = [0][1]
matrix[j][n-i-1] = temp_i_j;
参考文章
-
leetcode48** **旋转矩阵