描述
将一个正方形矩阵顺时针旋转 90 度。
分析
本题和转圈打印矩阵类似, 将矩阵分解成由外至内的方形圈,先处理最外层的圈,当最外层的圈中的元素都旋转到了正确位置后,再往里一层进行处理,直到最内层的圈处理完毕。处理每一层圈的过程是一致的,可以抽象出来。
处理每一圈的时候,可以先从四个角点出发。矩阵旋转 90 度后,四个角点会移动位置:O1 -> O2, O2 -> O3, O3 -> O4, O4 -> O1。可以通过两个点交换完成这样的移动,交换顺序为:O1 <> O2, O1 <> O4, O4 <> O3。完成三次点交换后,O1,O2,O3,O4 都到达了正确的位置。此时让四个点按箭头方向移动一格,继续重复点交换过程。直到 O1 到达圈的另一个角点,则处理当前圈的过程结束。
处理外层圈:
处理内层圈:
整体旋转后:
代码
class RotateMatrix {
public static void rotateMatrix(int[][] a) {
int xEnd = a.length - 1;
int yEnd = a[0].length - 1;
// x1、x2、x3、x4 初始为矩阵四个角点
int x1 = 0, y1 = 0;
int x2 = 0, y2 = yEnd;
int x3 = xEnd, y3 = yEnd;
int x4 = xEnd, y4 = 0;
while (x1 < x3) {
rotateCircle(a, x1++, y1++, x2++, y2--, x3--, y3--, x4--, y4++);
}
}
private static void rotateCircle(int[][]a, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
int end = y2;
while (y1 < end) { // O1 移动到 O2 左边一个位置时循环终止
swap(a, x1, y1, x2, y2); // 交换 O1 和 O2
swap(a, x1, y1, x4, y4); // 交换 O1 和 O4
swap(a, x4, y4, x3, y3); // 交换 O4 和 O3
y1++; // O1 向右移动一格
x2++; // O2 向下移动一格
y3--; // O3 向左移动一格
x4--; // O4 向上移动一格
}
}
// 交换两个点
private static void swap(int[][]a, int x1, int y1, int x2, int y2) {
int temp = a[x1][y1];
a[x1][y1] = a[x2][y2];
a[x2][y2] = temp;
}
public static void main(String[] args) {
// 设置原矩阵
int num = 0;
int[][] a = new int[4][4];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
a[i][j] = ++num;
}
}
// 打印原矩阵
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
// 旋转矩阵
rotateMatrix(a);
// 打印旋转后的矩阵
System.out.println();
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
}
}
out
原矩阵:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
旋转后:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4