前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >矩阵旋转,你转晕了吗?

矩阵旋转,你转晕了吗?

作者头像
ACM算法日常
发布2021-07-16 16:19:45
1.5K0
发布2021-07-16 16:19:45
举报
文章被收录于专栏:ACM算法日常

本次周赛第二题是一道矩阵旋转题目,本篇重点讨论一下旋转题目如何处理。

循环轮转矩阵

给你一个大小为 m x n 的整数矩阵 grid ,其中 m 和 n 都是 偶数 ;另给你一个整数 k 。返回执行 k 次循环轮转操作后的矩阵。

题解

本题的旋转不是旋转角度,而是旋转步数,我们可以先将矩阵分为多层,每一层单独旋转。

矩阵的层数是

min(m/2,n/2)

这道题比较有意思的地方是可以将每一层的数据放到一个数组中,然后走几步就是增加步数取余操作。可以理解为通过取余做成循环数组。

代码语言:javascript
复制
class Solution {
public:
    vector<vector<int>> rotateGrid(vector<vector<int>>& grid, int k) {
        int m = grid.size();
        int n = grid[0].size();
        int nlayer = min(m / 2, n / 2);   // 层数
        // 从左上角起逆时针枚举每一层
        for (int layer = 0; layer < nlayer; ++layer){
            vector<int> r, c, val;   // 每个元素的行下标,列下标与数值
            for (int i = layer; i < m - layer - 1; ++i){   // 左
                r.push_back(i);
                c.push_back(layer);
                val.push_back(grid[i][layer]);
            }
            for (int j = layer; j < n - layer - 1; ++j){   // 下
                r.push_back(m - layer - 1);
                c.push_back(j);
                val.push_back(grid[m-layer-1][j]);
            }
            for (int i = m - layer - 1; i > layer; --i){   // 右
                r.push_back(i);
                c.push_back(n - layer - 1);
                val.push_back(grid[i][n-layer-1]);
            }
            for (int j = n - layer - 1; j > layer; --j){   // 上
                r.push_back(layer);
                c.push_back(j);
                val.push_back(grid[layer][j]);
            }
            int total = val.size();   // 每一层的元素总数
            int kk = k % total;   // 等效轮转次数
            // 找到每个下标对应的轮转后的取值
            for (int i = 0; i < total; ++i){
                int idx = (i + total - kk) % total;   // 轮转后取值对应的下标
                grid[r[i]][c[i]] = val[idx];
            }
        }
        return grid;
    }
};

48. 旋转图像

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

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

题解

这一题是旋转角度,矩阵是正方形。这个题目要求原地旋转矩阵,也就是不使用额外的矩阵。这里先讲下如何使用额外的矩阵做法。

对于矩阵:

第一行旋转后是:

第二行旋转后是:

对于矩阵中的第三行和第四行同理。这样我们可以得到规律:

对于矩阵中第 i 行的第 j 个元素,在旋转后,它出现在倒数第 i 列的第 j 个位置

写成代码就是:

m[row][col]

变成了

m[col][n-row-1]

行变成了列,列变成了倒数的行。

代码语言:javascript
复制
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        
        auto matrix_new = matrix;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                matrix_new[j][n - i - 1] = matrix[i][j];
            }
        }
        
        matrix = matrix_new;
    }
};

原地旋转会复杂些,有2种思路,这里讲下简单的。

矩阵通过水平翻转和对角线翻转后刚好是旋转90的矩阵,如下图:

水平翻转

对角线翻转

代码语言:javascript
复制
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]);
            }
        }
    }
};

复杂的思路是使用一个临时变量存储一个位置,然后每次操作4个位置的变换,最终达到变换整个矩阵的目的,由于过程较为复杂,记忆难度较大,这里不细说了。

1886. 判断矩阵经轮转后是否一致

给你两个大小为 n x n 的二进制矩阵 mat 和 target 。现 以 90 度顺时针轮转 矩阵 mat 中的元素 若干次 ,如果能够使 mat 与 target 一致,返回 true ;否则,返回 false 。

实例:

题解

这道题是一道简单题,但是和48题一样的解法,48题是因为需要原地操作矩阵才是中等题。

代码语言:javascript
复制
class Solution {
public:
    bool findRotation(vector<vector<int>>& mat, vector<vector<int>>& target) {
        int n = mat.size();
        int m = mat[0].size();
        for (int i = 0; i < 4; ++i) {
            vector<vector<int>> tmp(n, vector<int>(m));
            for (int j = 0; j < n; ++j) {
                for (int k = 0; k < m; ++k) {
                    tmp[k][m - 1- j] = mat[j][k];
                }
            }
            if (tmp == target) return true;
            mat = tmp;
        }
        return false;
    }
};
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 循环轮转矩阵
  • 题解
  • 48. 旋转图像
  • 题解
  • 1886. 判断矩阵经轮转后是否一致
  • 题解
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档