LeetCode48-旋转图像 | 算法练习系列

375 阅读3分钟

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

前言

js每日一题算法题,今天继续来一道数组相关的算法题,这道题是旋转矩阵, 下面我们来具体看看题目要求

题目描述

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

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

  示例 1:

image.png

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

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

示例 2:

image.png

输入: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我们可以总结出翻转前的位置是matrix[i][j],翻转后的位置是matrix[j][n-row-1],也就是说原来旋转之后行号和列号进行的转换
  • 既然已经知道了转换的关系我们可以声明一个新的矩阵用作中间值,用来记录翻转后的矩阵,然后再把这个中间值矩阵通过for循环更细腻目标矩阵,具体代码如下
/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
var rotate = function(matrix) {
    const n = matrix.length;
    const curr = new Array(n).fill(0).map(() => new Array(n).fill(0));//这个就是声明的临时矩阵,用来记录翻转后的矩阵
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            curr[j][n - i - 1] = matrix[i][j];
        }
    }
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            matrix[i][j] = curr[i][j];
        }
    }
};
  • 上面这种方法可以解决问题但空间复杂度和时间复杂度上都不是最优的,我们观察matrix[j][n - i - 1] = matrix[i][j],这个公式阻碍了我们原地旋转矩阵,因为原地旋转的时候前面的值会被覆盖,那后面拿到的值就是错误的了
  • 上面这种方法还有待优化,通过实例我们可以看出旋转的情况其实可以分为总结情况,假设a,b,c,d四条边,旋转其实发生了四次位置的变换,我们只要找到这四个位置的变化规律,然后用一个变量就可以完成翻转了,由于时间问题这里就不贴具体的代码了

总结

算法题归根到底还是找规律,找通项公式,找转移方程,最主要的还是发现其中的关联,还需持续学习,gogogo