[算法]矩阵 螺旋矩阵II

例题

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1n^2 所有元素,且元素按顺时针顺序螺旋排列的 n * n 正方形矩阵 matrix

示例 1:

在这里插入图片描述

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

循环不变量原则

  • 本题并不涉及到什么算法,就是模拟过程。
  • 写循环的过程中一定要坚持循环不变量原则,此题可以让每条边都遵循左闭右开的原则,即将拐角处让给新的一条边来继续赋值。
  • 比如上述示例1中,第一条边包含元素1 2,第二条边包含元素3 4,第三条边包含元素5 6,第四条边包含元素7 8
  • 对于n为奇数的情况,还需要额外处理中心元素9
    • 可以直接在循环结束后对res[n/2][n/2]赋值;
    • 也可以在定义矩阵的时候直接将其初始化为n*n,这样就不必处理中心元素了。
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 使用vector定义一个二维数组,初始化为n*n,不必处理中心元素
        vector<vector<int>> res(n, vector<int>(n, n*n)); 

        // 遍历的起点
        int startx=0,starty=0;

        // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int offset=1;

        // 之所以要对ij初始化,是因为可能遇到n=1的情况
        int i=startx,j=starty;

        // 往res矩阵中赋的值
        int count=1;

        // 循环的圈数是n/2
        int loop=n/2;

        // 以示例1为例
        while(loop)
        {
            // 赋值1,2
            for(j=starty;j<n-offset;j++)
                res[startx][j]=count++;

            // 赋值3,4 
            for(i=startx;i<n-offset;i++)
                res[i][j]=count++;
            
            // 赋值5,6 
            for(;j>starty;j--)
                res[i][j]=count++;
            
            // 赋值7,8 
            for(;i>startx;i--)
                res[i][j]=count++;
            
            startx++;
            starty++;
            offset++;
            loop--;
        }
        return res;
    }
};

刷题

54. 螺旋矩阵

给你一个 mn 列的矩阵 matrix ,请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 2:

在这里插入图片描述

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
  • 与例题不同的是这里的矩阵包含了长方形矩阵,此时循环的圈数应该是长和宽中的最小值再除以2
  • 如果长宽中最小值是奇数,就会存在需要单独处理的行或列。
    • 如上述示例2的元素6 7
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        // m行n列矩阵
        // 注意测试集中存在[],需要对特殊情况进行处理
        int m=matrix.size();
        if(m==0)
            return {};
        int n=matrix[0].size();
        if(n==0)
            return {};
        
        // 初始化一个长度为m*n的一维数组
        vector<int> res(m*n);
        
        int startx=0,starty=0;
        int i=startx,j=starty;
        int offset=1;
        int index=0;
        
        int loop=min(m,n)/2;

        while(loop--)
        {
            for(j=starty;j<n-offset;j++)
                res[index++]=matrix[startx][j];
            for(i=startx;i<m-offset;i++)
                res[index++]=matrix[i][j];
            for(;j>starty;j--)
                res[index++]=matrix[i][j];
            for(;i>startx;i--)
                res[index++]=matrix[i][j];
            
            startx++;
            starty++;
            offset++;
        }

        if(min(m,n)%2)
        {
            // 在中间有多余的列
            if(m>n)
            {
                for(i=startx;i<m-offset+1;i++)
                    res[index++]=matrix[i][starty];
            }
            // 在中间有多余的行
            else
            {
                for(j=starty;j<n-offset+1;j++)
                    res[index++]=matrix[startx][j];
            }
        }
        return res;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值