每日一练:旋转图像

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]]

示例 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]]

提示:

  • n == matrix.length == matrix[i].length
  • 1 <= n <= 20
  • -1000 <= matrix[i][j] <= 1000

以上题目来自LeetCode

一、解法1-设定边界 O(N^2) 原地旋转

        这个题目与螺旋矩阵十分相似,也是可以设定边界,操作完外圈后再操作内圈。不同的是这个题目要改变矩阵的值。

传送门:每日一练:螺旋矩阵

        首先,这个题目要求矩阵顺时针旋转90°,物理上就是把矩阵向右推倒,就可以得到结果,但是在逻辑上需要我们自己一个一个的改变值。幸运的是,我们只要把最外层的旋转逻辑写好,更改边界就可以适用于内层的逻辑了,我们先找一下旋转的规律:

        以matrix[0][0]为参照,根据题目的例子在旋转前后对它的位置做记录:

矩阵边长顺时针移动格子数
32
43

         可以发现:移动距离=矩阵边长-1;

        (1)先写移动一格的逻辑;

        (2)根据边长决定移动次数;

        (3)移动完一层后更新边长和边界即可;

         为了方便,我是先记录边角的值,然后从后向前赋值的。

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int length_left = 0;                     // 左边界
        int length_right = matrix[0].size() - 1; // 右边界
        int width_top = 0;                       // 上边界
        int width_below = matrix.size() - 1;     // 下边界
        while (length_right - length_left > 0) {
            int n = length_right-length_left+1; // 边长
            for (int j = 0; j < n-1; j++) {
                int tmp1 = matrix[width_top][length_right];
                for (int i = length_right; i > length_left; i--) {
                    matrix[width_top][i] = matrix[width_top][i - 1];
                }

                int tmp2 = matrix[width_below][length_right];
                for (int i = width_below; i > width_top + 1; i--) {
                    matrix[i][length_right] = matrix[i - 1][length_right];
                }
                matrix[width_top + 1][length_right] = tmp1;

                int tmp3 = matrix[width_below][length_left];
                for (int i = length_left; i < length_right - 1; i++) {
                    matrix[width_below][i] = matrix[width_below][i + 1];
                }
                matrix[width_below][length_right - 1] = tmp2;

                for (int i = width_top; i < width_below - 1; i++) {
                    matrix[i][length_left] = matrix[i + 1][length_left];
                }
                matrix[width_below - 1][length_left] = tmp3;
            }
            // 更新边界
            length_left++;
            length_right--;
            width_top++;
            width_below--;
        }
    }
};

       内存优化:

        实际上这个题目要求矩阵是个正方形,所以每次循环时 length_right 与 width_below 是一样的,统一用 rb 表示; length_left 与 width_top 也是一样的,统一用 lt 表示,优化后的代码如下:

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int lt = 0;                    // 左边界+上边界
        int rb = matrix[0].size() - 1; // 右边界+下边界
        while (rb - lt > 0) {
            for (int j = 0; j < rb-lt; j++) {
                int tmp1 = matrix[lt][rb];
                for (int i = rb; i > lt; i--) {
                    matrix[lt][i] = matrix[lt][i - 1];
                }

                int tmp2 = matrix[rb][rb];
                for (int i = rb; i > lt + 1; i--) {
                    matrix[i][rb] = matrix[i - 1][rb];
                }
                matrix[lt + 1][rb] = tmp1;

                int tmp3 = matrix[rb][lt];
                for (int i = lt; i < rb - 1; i++) {
                    matrix[rb][i] = matrix[rb][i + 1];
                }
                matrix[rb][rb - 1] = tmp2;

                for (int i = lt; i < rb - 1; i++) {
                    matrix[i][lt] = matrix[i + 1][lt];
                }
                matrix[rb - 1][lt] = tmp3;
            }
            // 更新边界
            lt++;
            rb--;
        }
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值