前端刷题路-Day64:旋转图像(题号48)

339 阅读1分钟

这是我参与更文挑战的第28天,活动详情查看: 更文挑战

旋转图像(题号48)

题目

给定一个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]]

示例 3:

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

示例 4:

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

提示:

  • matrix.length == n
  • matrix[i].length == n
  • 1 <= n <= 20
  • -1000 <= matrix[i][j] <= 1000

链接

leetcode-cn.com/problems/ro…

解释

这题啊,这题是小学二年级就学过的找规律。

首先,最简单的解法就是搞一个新的数组,将修改后的数据填入到新数组中,完事之后再循环新数组,将原数组替换一下就好了。

那还有什么其他方法么?显然是有的,官方给出了两种思路👇:

  1. 一次性旋转

    一次性旋转就是遍历到一个元素的时候,直接将它翻转四次,更新四个位置

  2. 先垂直翻转,再对角线翻转

    这个思路比较简单一些,现实进行上下的翻转,之后从左上角到右下角画一条对角线,翻转对角线两边的元素也能得到最后的答案。

其实就是找规律嘛,怎样操作才能得到最后的结果,确实是这个逻辑。

自己的答案(借用数组)

这种答案大家应该都能想到,翻转的逻辑很简单。

比方说第一行翻转👇:

[51911]>[51911]\left[ \begin{matrix} 5 & 1 & 9 & 11 \\ ∘ & ∘ & ∘ & ∘ \\ ∘ & ∘ & ∘ & ∘ \\ ∘ & ∘ & ∘ & ∘ \\ \end{matrix} \right] -> \left[ \begin{matrix} ∘ & ∘ & ∘ & 5 \\ ∘ & ∘ & ∘ & 1 \\ ∘ & ∘ & ∘ & 9 \\ ∘ & ∘ & ∘ & 11 \\ \end{matrix} \right]

第二行翻转同理可得👇:

[24810]>[24810]\left[ \begin{matrix} ∘ & ∘ & ∘ & ∘ \\ 2 & 4 & 8 & 10 \\ ∘ & ∘ & ∘ & ∘ \\ ∘ & ∘ & ∘ & ∘ \\ \end{matrix} \right] -> \left[ \begin{matrix} ∘ & ∘ & 2 & ∘ \\ ∘ & ∘ & 4 & ∘ \\ ∘ & ∘ & 8 & ∘ \\ ∘ & ∘ & 10 & ∘ \\ \end{matrix} \right]

然后就是简单的代码👇:

var rotate = function(matrix) {
  var n = matrix.length
      newMatrix = Array.from({length: n}, () => new Array(n))
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      newMatrix[j][n - i - 1] = matrix[i][j]
    }    
  }
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      matrix[i][j] = newMatrix[i][j]
    }    
  }
  return matrix
};

没啥可说的,新建数组然后替换就好了。

更好的方法(垂直翻转+对角线翻转)

这个方法也简单,反正感觉比一步到位的方法好很多。

首先上下翻转,这个倒是简单,不过这里需要记住只能翻转一半,如果全都翻转了就又和原来一样了。

然后是对角线翻转,由于那条对角线上的数字不用动,那么剩下的只要交换xy的位置就好了。

放到代码里是这样的👇:

var rotate = function(matrix) {
  var n = matrix.length
  // 垂直翻转
  for (let i = 0; i < ~~(n / 2); i++) {
    for (let j = 0; j < n; j++) {
      [matrix[i][j], matrix[n - i - 1][j]] = [matrix[n - i - 1][j], matrix[i][j]]
    }
  }
  // 对角线翻转
  for (let i = 0; i < n; i++) {
    for (let j = i + 1; j < n; j++) {
      [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]]
    }
  }
  return matrix
};

垂直翻转这里需要注意,不能按行翻转,因为数组是复杂对象,如果直接赋值的话就直接改了引用的内存地址,所以还是需要一个个的进行赋值操作才可以。

对角线翻转就更简单一些了,由于对角线上的数不需要翻转的,那么旋转的个数是逐渐减少的,也是翻转一半就行了。

翻转过程也是直接替换xy就行。

更好的方法(一次性翻转)

这个方法的求导过程及其复杂,以笔者的智商就算看懂了,下次应该也记不住,这里放弃了,感兴趣的同学可以看看官方答案,过程十分详细。

点击这里直达官方答案



PS:想查看往期文章和题目可以点击下面的链接:

这里是按照日期分类的👇

前端刷题路-目录(日期分类)

经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇

前端刷题路-目录(题型分类)

有兴趣的也可以看看我的个人主页👇

Here is RZ