旋转图像

旋转图像

思路:

第一意识是找一个数学规律,一个公式可以找到对应的位置。

唉 想不出 没啥思路 看题解了。

一看就懂了 规律就是。。。。。。:原来第 i 行第 j 列的元素 在旋转后 会在第 j 行倒数第i列。

这种题目做少了,多做几个矩阵的总结一下规律就懂了。

法一:这是利用辅助矩阵的方法。

cpp 复制代码
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        // C++ 这里的 = 拷贝是值拷贝,会得到一个新的数组
        auto matrix_new = matrix;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {//翻转后矩阵的[i][j]是之前的[n-1-j][i]
                matrix_new[i][j]=matrix[n-1-j][i];
            }
        }
        matrix=matrix_new;//再来一次值拷贝
    }
};

法二:不使用辅助数组,原地进行操作,故需要考虑覆盖问题。

为什么要这么想呢,可以从n=2,3看看,可以发现旋转都是很有规律的!!!

法二是利用一个关键公式进行推导:

复制代码
  matrix_new[j][n - i - 1] = matrix[i][j];

这个公式的意思是,原来**ij** 位置的元素 要旋转到**jn-i-1**。

这个时候**jn-i-1**就要被覆盖了,我们继续看看这个位置的值旋转后要去哪。

继续代入关键公式,即令i=j,j=n-i-1 我们可以得到**jn-i-1** 要旋转到**n-i-1n-j-1**的位置、

我们继续看**n-i-1n-j-1** 要旋转到哪里: 令i=n-i-1,j=n-j-1,我们可以得到**n-i-1n-j-1**要旋转到

n-j-1i 的位置。继续看**,** 同理,n-j-1i 要旋转到**ij**

可以大声喊我艹了。我们惊奇的发现闭环了,也就是**ij旋转到jn-i-1,jn-i-1旋转到n-i-1n-j-1,n-i-1n-j-1旋转到n-j-1i,n-j-1i又旋转到ij,形成了闭环!!**

这个时候,我们每次遍历处理四个元素就可以了,处理这四个元素的时候,存一下ij,即temp=ij,就可以对后续都进行原地赋值操作。即以下五行代码:

temp=ij;

ij= n-j-1i;

n-j-1i=n-i-1n-j-1;

n-i-1n-j-1=jn-i-1;

jn-i-1=temp;

每一次处理四个元素,总共有n*n个元素。

然后剩下的问题是如何确定遍历的范围:

  • 因为每次遍历都是操作4个点,显然我们只需遍历n*n/4个格子即可.
  • 直觉上n*n/4可以等于 (n/2) * (n/2) (即0 <= i < n/2 ,0 <= j < (n/2)),
  • 但也可以等于n * (n/4),究竟是哪种呢?
  • 可以自己模拟一下n=2 n=3就明白了。肯定是前者。
  • n为偶数的时候是四等分:
  • n为奇数时:
  • 综上,不管n是奇数还是偶数,遍历的范围都可以表示为0 <= i < n/2 ,0 <= j < ( n+1 /2)

代码:

cpp 复制代码
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+1)/2;j++)
            {
                int temp=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]=temp;
            }
        }
    }
};

法三:一些巧妙的方法:用翻转代替旋转

用两次翻转代替旋转:

为什么呢?

我们也分别列出沿水平翻转和沿主对角线翻转的公式:

沿水平翻转:matrix_newn-i-1j=matrixij

沿对角线翻转:matrix_newji=matrixij

这两个联立,可以得到。可以得到matrix_newjn-i-1=matrixij 而这个就是之前说到的关键公式。所以两次翻转就等于将图像顺时针旋转 90 度。

而这种翻转,直接用swap就好了。

代码:

cpp 复制代码
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++)
            {
                swap(matrix[i][j],matrix[n-i-1][j]);
            }
        }
        for(int i=0;i<n;i++)//对角线翻转
        {
            for(int j=0;j<i;j++)
            {
                swap(matrix[i][j],matrix[j][i]);
            }
        }
    }
};
相关推荐
weixin_307779132 小时前
C++代码实现MATLAB中的dlarray函数功能
开发语言·c++·算法·matlab
hetao17338378 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
Zootopia6268 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan8 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
2601_9603563810 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah10 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO910 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician10 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
垆边人似月.10 小时前
VLAN 资源池(100~200 分档)
数据结构·算法
潼心1412o11 小时前
C++初阶(长期更新)第6讲:类和对象(下)
开发语言·c++·算法