螺旋矩阵II

螺旋矩阵II

题目链接

题目

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

示例:

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


思路一:

模拟顺时针画矩阵的过程:

填充上行从左到右
填充右列从上到下
填充下行从右到左
填充左列从下到上
由外向内一圈一圈这么画下去。

注意循环不变量:每行/列不走满,开头留一格或结尾留一格

重点:判断碰头,若下一位不为零,则继续按照之前的方向前进,否则转向


代码一(每个方向的行走规则各写一个)

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n,vector<int>(n,0));//创建二维数组

        int i=0,j=0;
        int cnt=1;

        res[0][0] = 1;
		
        while(cnt<n*n){
            while(j<n-1 && res[i][j+1]==0)res[i][++j] = ++cnt;
            while(i<n-1 && res[i+1][j]==0)res[++i][j] = ++cnt;
            while(j>0 && res[i][j-1]==0)res[i][--j] = ++cnt;
            while(i>0 && res[i-1][j]==0)res[--i][j] = ++cnt;
        }

        return res;
    }
};

代码二(利用方向向量转向)

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int dx = 0, dy = 1;  //方向向量
        int x = 0, y = 0;
        for (int i = 1; i <= n * n; ++i) {
            res[x][y] = i;
            //判断下一位是否已经有数字,注意加n再取模,防止数组越界
            if (res[(x + dx + n) % n][(y + dy + n) % n] != 0) {
                //若有数字,则向右转向,令(dx,dy)-->(dy,-dx)
                int tmp = dy;
                dy = -dx;
                dx = tmp;
            }
            
            //依据方向向量移动
            x += dx;
            y += dy;
        }
        return res;
    }
};

思路二:

这里的方法不需要记录已经走过的路径,所以执行用时和内存消耗都相对较小

  1. 首先设定上下左右边界
  2. 其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界
  3. 判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案
  4. 若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理
  5. 不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案

代码三(删除走过的边)

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int up=0,down=n-1,l=0,r=n-1;//上边界up,下边界down,左边界l,右边界r
        int cnt = 1;
        int i=0,j=0;
        while(true){
            for(i=up,j=l;j<=r;j++)res[i][j]=cnt++;
            if(++up > down)break;
            for(i=up,j=r;i<=down;i++)res[i][j]=cnt++;
            if(--r < l)break;
            for(i=down,j=r;j>=l;j--)res[i][j]=cnt++;
            if(--down < up)break;
            for(i=down,j=l;i>=up;i--)res[i][j]=cnt++;
            if(++l > r)break;
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值