Leetcode48.旋转图像

题目描述:

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

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

输入: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]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotate-image

Intuition: 

我们可以观察旋转前后的矩阵得到结论,原矩阵中位于第 i 行,第 j 列的数, 在旋转之后,将移位到第 j 行,倒数第i 列的位置上去。

 max[row][col] = max[col][n - 1 - row]

具体实现 

两种方法。第一种为循环流动。第二种为翻转

方法一:

逐“圈”进行循环,以题目描述中的示例为例

蓝色为第一圈,橙色为第二圈。逐圈往里收紧直到中心点。

在每一圈中,都可以分为几个组。

在第一圈中,我们先来看第一组{5,11,16,15},也就是二维矩阵的四个角。数字5移动到数字11的位置,数字11移动到数字16的位置。数字16移动到数字15的位置,数字15移动到数字5的位置,也就是说,这四个数字为一组,每一个数字都循环流动到了下一个位置。

仍然是第一圈,继续。第二组{1,10,12,13},第三组{9,17,14,2}同理流动。

第一圈完成,第二圈同理流动。

 圈为外循环,组为内循环。具体实现如下。

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int i , j;
        int n = matrix.size();
        for(i = 0; i < n / 2; i++){
            for(j = i ; j < n - 1 - i ; j++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n - 1 - j][i];
                matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j];
                matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i];
                matrix[j][n - 1 - i] = temp;

            }
        }
        
    }
};

循环体中,流动的具体实现与intuition有所区别的原因所在,是因为先保存下来了第一个数字,然后让每组最后一个数字先填入第一个数字所在的位置,接着倒数第二个数字填入最后一个数字所在的位置,相当于和intuition倒着来,最后将第一个数字填入第二个数字所在的位置中。原理都是相同的。

方法二:

在一维数组的循环数组题目中,我们采用了,先翻转前部数组,再翻转后部数组,最后整体翻转的策略。这个思路也可以应用到二维数组中,通过翻转来简化实现。

在本题中,采用先水平方向上下翻转,再沿着正对角线镜像的方法,来实现顺时针旋转九十度的效果。具体实现如下:

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

事实上,

水平翻转相当于matrix[row][col] =  matrix[n-1-row][col]。

沿正对角线镜像相当于matrix[n-1-row][col]=matrix[col][n-1-row]。

不难看出,两个式子结合,与Intuition仍然是相符的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值