Leetcode-48 旋转图像(矩阵旋转)

这篇博客介绍了LeetCode 48题的解决方法,重点在于如何原地旋转矩阵。首先,作者分享了一个不满足原地旋转要求的思路,然后详细解释了两种有效的方法:一是先转置再逐行翻转,二是通过矩阵元素的四向交换实现旋转。C++代码示例展示了这两种方法的实现,时间复杂度均为O(n^2)。博客强调了解决问题的关键在于观察和找寻规律。
摘要由CSDN通过智能技术生成

Leetcode48题
题目特别强调需要原地旋转图像,苦思无果。
只想到一个方法,发现矩阵第一行旋转90°插入第n列、矩阵第二行旋转90°插入第n-1列······以此类推,直到最后一行,就可以得到旋转图像。遗憾的是,处理完矩阵第一行之后,其余其他行的最后一个元素就改变了······因此就需要额外的空间存储未改变之前的数据,不符题意。

后来看了别人的解法,我们可以称之为方法一:观察发现先将矩阵转置后逐行翻转就会得到旋转图像。简洁易理解,我也就不再解释了。

C++代码如下:

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n=matrix.size();
        for(int i=0;i<n;i++)
        {
            for(int j=i;j<n;j++)
            {
                int m=0;
                m=matrix[i][j];
                matrix[i][j]=matrix[j][i];
                matrix[j][i]=m;
            }
        }
        for(int i=0;i<n;i++)
        {
            int j=0;
            int k=n-1;
            while(j<k)
            {
                int m=0;
                m=matrix[i][j];
                matrix[i][j]=matrix[i][k];
                matrix[i][k]=m;
                j++;
                k--;
            }
        }
    }
};

时间复杂度:O(n^2)
总结:要善于观察,将一个陌生的过程通过观察拆解成为自己熟悉的几个过程,逐个击破得到解法。

从官方给的解法里面,还有其他方法,我们称之为方法二:单看矩阵中一个元素A的话,我们可以知道他旋转之后的位置,A旋转过去,势必要挤掉原本在这个位置的元素,我们称其为B,B的旋转与A同理······B挤掉C,C挤掉D,D旋转之后又回到了A的原本的位置。图像旋转的本质就是这四个数的相互交换,其他元素怎么动不会影响到这四个数的轨迹,反之亦然。当矩阵中的每一个元素都只动过一次时,便得到了整个矩阵的旋转图像。由此可见,将矩阵中的元素按照如上方式四个元素分为一组,每组内四个元素之间相互交换。

将思想转化为代码,如果将矩阵按照行优先一个一个遍历,还要判断当前元素是否已经移动过,着实太麻烦。如图所示,如果将矩阵按照如图所示分成层的话,可以发现,同一组的元素只会出现在同一层,他们之间的变动不会影响其他层,因此我们可以从外向内层层变动。
在这里插入图片描述
另外,对于某一层而言,他有A,B,C,D四条边,设边长为n,层内可分组为(A[0]B[0]C[0]D[0])(A[1]B[1]C[1]D[1])······又由于,我们只要得到A[0]的坐标,便可以推算出B[0]C[0]D[0]的坐标,A[1]亦然······所以只要遍历某层任意一条边上的n-1个元素并进行操作,就可以完成对整层的旋转,而无需考虑该层其他边
这样就大大减少了遍历的次数,也无需判断该元素是否已经移动过。

设A[0]坐标为(i,j) ,则B[0]坐标为(j, n-i-1),C[0]坐标为(n-i-1, n-j-1), D[0]坐标为(n -j-1, i),其中n为矩阵的行数或者列数

C++代码如下:

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n=matrix.size();
        for(int i=0;i<n/2;i++)
        {
            for(int j=i;j<n-i-1;j++)
            {
                int k=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]=k;
            }
        }
    }
};

时间复杂度:O(n^2)。
总结:与前一种方法相比,方法一像是在宏观上思考并解决问题,方法二像是在微观上思考并解决问题,让我联想起物理学。共同点就是找规律,不过感觉方法二的规律更难找而且更难下手写出代码。

如果我哪里写错了还望各位大佬在评论区与我交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值