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]]

示例 3:

输入:matrix = [[1]]
输出:[[1]]

示例 4:

输入:matrix = [[1,2],[3,4]]
输出:[[3,1],[4,2]]

解法

1、先上下交换,再沿对角线交换

/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
var rotate = function (matrix) {
  const length = matrix.length;

  // 先上下交换
  for (let i = 0; i < length / 2; i++) {
    const temp = matrix[i];
    matrix[i] = matrix[length - i - 1];
    matrix[length - i - 1] = temp;
  }

  // 在按照对角线交换
  for (let i = 0; i < length; i++) {
    for (let j = i + 1; j < length; j++) {
      const temp = matrix[i][j];

      matrix[i][j] = matrix[j][i];
      matrix[j][i] = temp;
    }
  }
};

2,直接交换

题中说了是顺时针旋转 90 度,通过旋转其实可以发现一个规律,只需要一圈一圈的旋转即可。

/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
var rotate = function (matrix) {
  const length = matrix.length;

  // 因为是对称的,只需要计算循环前半行即可(这句话其实我没太看懂)
  for (let i = 0; i < length / 2; i++)
    for (let j = i; j < length - i - 1; j++) {
      let temp = matrix[i][j];
      let m = length - j - 1;
      let n = length - i - 1;
      matrix[i][j] = matrix[m][i];
      matrix[m][i] = matrix[n][m];
      matrix[n][m] = matrix[j][n];
      matrix[j][n] = temp;
    }
};

方法二的交换策略可以说的方法一的一种升级了, 直接旋转交换。下面我通过枚举遍历循环查看详细数据。

length = 4
i < 2
j < 4 - i -1

// 第一轮循环
i = 0;
j < 3

i = 0, j = 0
m = 3, n = 3
[0][0] = [3][0], 5 = 15
[3][0] = [3][3], 15 = 16
[3][3] = [0][3], 16 = 11
[0][3] = [0][0], 11 = 5

// 第二轮循环
i = 0, j = 1

m = 2, m = 3
[0][1] = [2][0], 1 = 13
[2][0] = [3][2], 13 = 12
[3][2] = [1][3], 12 = 10
[1][3] = [0][1], 10 = 1


// 第三轮循环

i = 0, j = 2

m = 1, n = 3
[0][2] = [1][0], 9 = 2
[1][0] = [3][1], 2 = 14
[3][1] = [2][3], 14 = 7
[2][3] = [0][2], 7 = 9


// 前面三轮循环都是旋转外层的数据, 分别对, j = 0,1,2 三种情况进行了旋转,使得整个外层旋转完成
// 下面即是对内层进行旋转

// 内层,循环,第一轮循环

i = 1, i < 2
j = 1, j < 2

m = 2, n = 2

[1][1] = [2][1], 4 = 3
[2][1] = [2][2], 3 = 8
[2][2] = [1][2], 6 = 8
[1][2] = [1][1], 8 = 4