48. 旋转图像

链接:48. 旋转图像 - 力扣(LeetCode)

题目描述

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

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

示例 1:

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

思路提示

方法一:原地计算

        将每个位置旋转到对应位置,如下:

        从中可以看出,每次轮回需要涉及四次交换,为避免覆盖原值,需要先将原值存入临时变量。如先将(0,0)的值存入temp,再用(3,0)替换(0,0),(3,3)替换(3,0),(0,3)替换(3,0),最后temp替换(0,3)。下一轮是(2,0)->(0,1),(3,2)->(2,0),(1,3)->(3,2),temp -> (0,1)。由此类推,可知

  •         第 i 行 j 列的元素matrix(i,j)被第 i 列的元素替代,第 i 列的元素的行号与被替换的元素的列号 j 之和刚好为矩阵长度length-1,设为 m = length - 1 - j。
  •         第 m 行 i 列的元素matrix(m,i)被第 m 列的元素替代,第 m 列的元素的行号与被替换的列号 i 之和为length - 1,设为 n = length - 1 -  i。
  •         第 n 行 m 列的元素matrix(n,m)被第 n 列的元素替代,第 n 列的元素的行号刚好为元素matrix(i,j)的列号 j 。
  • j方向总是从i开始进行到length-1-i的时候跳出,即进入下一个圈。
代码实现
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int length = matrix.size();
        //因为是对称的,只需要计算循环前半行即可
        for (int i = 0; i < length / 2; i++)
            for (int j = i; j < length - i - 1; j++) {//外圈旋转完毕,内圈开始旋转
                int temp = matrix[i][j];
                int m = length - j - 1;
                int 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;
            }
    }
};

方法二:翻转代替旋转

我们还可以另辟蹊径,用翻转操作代替旋转操作。我们还是以题目中的示例二


作为例子,先将其通过水平轴翻转得到:


再根据主对角线翻转得到:


        就得到了答案。这是为什么呢?对于水平轴翻转而言,我们只需要枚举矩阵上半部分的元素,和下半部分的元素进行交换,即

对于主对角线翻转而言,我们只需要枚举对角线左侧的元素,和右侧的元素进行交换,即

将它们联立即可得到:

即可得到翻转后的位置。

代码实现
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n=matrix.size();

        for(int i=0;i<n/2;++i){//上下对称,只需交换一半,如果全部遍历就会恢复为原数组
            for(int j=0;j<n;++j){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n-i-1][j];
                matrix[n-i-1][j] = temp;
            }
        }
        // for(int i=0;i<n;++i){
        //     for(int j=0;j<i;++j){//从(i,j)交换到(i-1,i-1),即遍历左下角一半的数组
        //         int temp = matrix[i][j];
        //         matrix[i][j] = matrix[j][i];
        //         matrix[j][i] = temp;
        //     }
        // }
        for(int i=0;i<n-1;++i){
            for(int j=i+1;j<n;++j){//遍历右上角的数组
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
    }
};

 通过试验发现,采用交换函数swap, swap(matrix[i][j],matrix[n-i-1][j]);由于时间太短看不出提升,内存反而多了一丢丢。

        一般情况下,使用swap函数比手动编写赋值代码更快。swap函数是C++标准库中提供的函数,它使用了优化的实现方式,能够高效地交换两个对象的值。相比之下,手动编写的赋值代码可能需要更多的指令和操作来完成交换过程,因此通常会更慢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值