leetcode-第247场周赛-5798循环轮转矩阵(模拟题)

5798. 循环轮转矩阵(模拟题)

题目链接:https://leetcode-cn.com/problems/cyclically-rotating-a-grid/

题目:

给你一个大小为 m x n 的整数矩阵 grid​​​ ,其中 m 和 n 都是 偶数 ;另给你一个整数 k 。矩阵由若干层组成,如下图所示,每种颜色代表一层:
在这里插入图片描述
矩阵的循环轮转是通过分别循环轮转矩阵中的每一层完成的。在对某一层进行一次循环旋转操作时,层中的每一个元素将会取代其 逆时针 方向的相邻元素。轮转示例如下:
在这里插入图片描述
返回执行 k 次循环轮转操作后的矩阵。


示例 1:

在这里插入图片描述

输入: grid = [[40,10],[30,20]], k = 1
输出: [[10,20],[40,30]]
解释: 上图展示了矩阵在执行循环轮转操作时每一步的状态。

示例 2:

在这里插入图片描述

输入: grid = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], k = 2
输出: [[3,4,8,12],[2,11,10,16],[1,7,6,15],[5,9,13,14]]
解释: 上图展示了矩阵在执行循环轮转操作时每一步的状态。

注意:

  • m == grid.length
  • n == grid[i].length
  • 2 <= m, n <= 50
  • m 和 n 都是 偶数
  • 1 <= grid[i][j] <= 5000
  • 1 <= k <= 1 0 9 10^9 109

解题思路:

题意很清晰,沿着矩阵边缘绕一圈,一层又一层,就跟削苹果似的,分层效果如下图:
在这里插入图片描述

我们令n、m为矩阵的高和宽,那么我们沿着矩阵边缘能够分成多少层呢?经过简单的计算,我们就会知道
层 数 为 : m i n ( n , m ) / 2 层数为:min(n,m)/2 minn,m/2
题目是要让我们对每一层都进行逆时针移动k步,问我们移动k步之后矩阵是什么样子的。

观察k的取值范围,我们会发现是很大的,高达 1 0 9 10^9 109。移动 1 0 9 10^9 109步的时间复杂度是很高的,我们有什么办法能够降低时间复杂度呢?
假 如 我 们 的 这 一 层 长 度 为 l , 需 要 逆 时 针 移 动 k 步 。 那 么 我 们 发 现 移 动 l % k 和 移 动 l 步 是 等 价 的 假如我们的这一层长度为l,需要逆时针移动k步。那么我们发现移动l\%k和移动l 步是等价的 l,kl%kl

那么我们只需要求这一层的长度 l l l,移动 l % k l\%k l%k步就可以了。我们假设 l e f t 、 r i g h t 、 t o p 、 b o t t o m left、right、top、bottom leftrighttopbottom分别对应的是这一层的左边界、右边界、上边界、下边界,那么 l l l
l = ( b o t t o m − t o p + 1 ) ∗ 2 + ( r i g h t − l e f t − 1 ) ∗ 2 l=(bottom-top+1)*2+(right-left-1)*2 l=(bottomtop+1)2+(rightleft1)2
在这里插入图片描述

接下来我们就需要模拟逆时针先移动一步。核心代码如下:

				for(int i=bottom;i>top;i--)
                grid[i][left]=grid[i-1][left]; //left
                grid[top][left]=top_left;

                for(int j=right;j>left+1;j--)
                grid[bottom][j]=grid[bottom][j-1]; // bottom
                grid[bottom][left+1]=bottom_left;

                for(int i=top;i<bottom-1;i++) //right
                grid[i][right]=grid[i+1][right];
                grid[bottom-1][right]=bottom_right;

                for(int j=left+1;j<right-1;j++)//top
                grid[top][j]=grid[top][j+1];
                grid[top][right-1]=top_right;

leetcode AC代码

class Solution {
public:
    vector<vector<int>> rotateGrid(vector<vector<int>>& grid, int k) {
        int n,m;
        n=grid.size();
        m=grid[0].size();
        int top,bottom,left,right,sum,t;
        int bottom_left,bottom_right,top_left,top_right;
        
        for(int ii=0;ii<min(n,m)/2;ii++)
        {
            top=ii;
            bottom=n-1-ii;
            left=ii;
            right=m-1-ii;

            sum=(bottom-top+1)*2+(right-left-1)*2;
            /*if(sum==0)
            {
                vector<int>in;
                in.push_back(1);
                in.push_back(1);
                in.push_back(1);
                vector<vector<int>> out;
                out.push_back(in);
                return out;
            }*/
            t=k%sum;

            while(t--)
            {
                top_left=grid[top][left+1]; 
                bottom_left=grid[bottom][left];
                bottom_right=grid[bottom][right];
                top_right=grid[top][right];

                for(int i=bottom;i>top;i--)
                grid[i][left]=grid[i-1][left]; //left
                grid[top][left]=top_left;

                for(int j=right;j>left+1;j--)
                grid[bottom][j]=grid[bottom][j-1]; // bottom
                grid[bottom][left+1]=bottom_left;

                for(int i=top;i<bottom-1;i++) //right
                grid[i][right]=grid[i+1][right];
                //grid[top][right-1]=top_right;
                grid[bottom-1][right]=bottom_right;

                for(int j=left+1;j<right-1;j++)//top
                grid[top][j]=grid[top][j+1];
                grid[top][right-1]=top_right;

            }
        }

        return grid;
    }
};

最后感谢小伙伴们的学习噢~
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__Wedream__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值