48_旋转图像(算法思路,时间和复杂度分析)

115 阅读3分钟

题目描述

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在** 原地** 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

img

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

示例 2:

img

输入: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]]

思路

  1. 新开一个数组,原数组第一行变成新数组最后一列,第二行变成倒数第二列...再对新数组重新赋值
  2. 原地置换
    • 这道题leetcode官方题解很清楚,leetcode.cn/problems/ro…
    • 简单来讲思路就是我们对数组元素进行轮转替换,拿示例1举例子,先对元素1进行轮转,位置发生改变的有4个元素,即1,3,9,7;第一次轮转后,1->3, 3 -> 9, 9 -> 7, 7 -> 1;这样轮转了1圈,我们可以从左下角开始轮转,使用一个临时变量temp保存左下角的值,9到7的位置上,3到9的位置上,1到3的位置上,最后temp到1的位置上,就完成了1轮轮转
    • 行的遍历范围for(let i = 0; i < Math.floor(n / 2); i++) 只需要遍历矩阵的前半部分行,因为旋转是对称的,后半部分行的元素会在前半部分行的旋转过程中自动处理。
    • 列的遍历范围for(let j = 0; j < Math.floor((n + 1) / 2); j++) 对于奇数维度的矩阵,中间列的元素只需要处理一次,因此使用Math.floor((n + 1) / 2)确保中间列在奇数情况下被包括进来,而在偶数情况下遍历所有必要的列。
  3. 先水平翻转,再对角线翻转

复杂度分析

时间复杂度

  • O(n²):需要遍历整个矩阵中的每个元素一次,因此时间复杂度为二次方。

空间复杂度

  • O(1):原地旋转,不需要额外的空间来存储结果,空间复杂度为常数级别。

code

/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
var rotate = function (matrix) {
    const n = matrix.length
    for(let i = 0; i < Math.floor(n / 2); i++){
        for(let j = 0; j < Math.floor((n + 1) / 2); j++){
            const temp = matrix[i][j]
            matrix[i][j] = matrix[n - j - 1][i]
            matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1]
            matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1]
            matrix[j][n - i - 1] = temp
        }
    }
};
  • 外层循环 ([i](vscode-file://vscode-app/d:/Microsoft VS Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html)) 遍历矩阵的前半部分行。
  • 内层循环 (j) 遍历每行的前半部分列。
  • 轮转过程:
    1. 保存当前元素 matrix[i][j]temp
    2. 将左下角的元素 matrix[n - j - 1][i] 赋值给当前元素 matrix[i][j]
    3. 将右下角的元素 matrix[n - i - 1][n - j - 1] 赋值给左下角的位置。
    4. 将右上角的元素 matrix[j][n - i - 1] 赋值给右下角的位置。
    5. 最后,将 temp 中保存的原始元素赋值给右上角的位置。