这是我参与更文挑战的第28天,活动详情查看: 更文挑战
旋转图像(题号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]]
提示:
matrix.length == nmatrix[i].length == n1 <= n <= 20-1000 <= matrix[i][j] <= 1000
链接
解释
这题啊,这题是小学二年级就学过的找规律。
首先,最简单的解法就是搞一个新的数组,将修改后的数据填入到新数组中,完事之后再循环新数组,将原数组替换一下就好了。
那还有什么其他方法么?显然是有的,官方给出了两种思路👇:
-
一次性旋转
一次性旋转就是遍历到一个元素的时候,直接将它翻转四次,更新四个位置
-
先垂直翻转,再对角线翻转
这个思路比较简单一些,现实进行上下的翻转,之后从左上角到右下角画一条对角线,翻转对角线两边的元素也能得到最后的答案。
其实就是找规律嘛,怎样操作才能得到最后的结果,确实是这个逻辑。
自己的答案(借用数组)
这种答案大家应该都能想到,翻转的逻辑很简单。
比方说第一行翻转👇:
第二行翻转同理可得👇:
然后就是简单的代码👇:
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
};
没啥可说的,新建数组然后替换就好了。
更好的方法(垂直翻转+对角线翻转)
这个方法也简单,反正感觉比一步到位的方法好很多。
首先上下翻转,这个倒是简单,不过这里需要记住只能翻转一半,如果全都翻转了就又和原来一样了。
然后是对角线翻转,由于那条对角线上的数字不用动,那么剩下的只要交换x和y的位置就好了。
放到代码里是这样的👇:
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
};
垂直翻转这里需要注意,不能按行翻转,因为数组是复杂对象,如果直接赋值的话就直接改了引用的内存地址,所以还是需要一个个的进行赋值操作才可以。
对角线翻转就更简单一些了,由于对角线上的数不需要翻转的,那么旋转的个数是逐渐减少的,也是翻转一半就行了。
翻转过程也是直接替换x、y就行。
更好的方法(一次性翻转)
这个方法的求导过程及其复杂,以笔者的智商就算看懂了,下次应该也记不住,这里放弃了,感兴趣的同学可以看看官方答案,过程十分详细。
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇
有兴趣的也可以看看我的个人主页👇