力扣每日一题:螺旋矩阵2

每日一题:螺旋矩阵2

今天的每日一题和昨天的题目相似,昨天的题目是对于任意给定的矩阵螺旋输出结果,采用的方法是路径模拟:从起点开始向前移动,碰到墙壁或者来到已访问过的地方就顺时针旋转,一直重复m*n次。今天的题目是给定正整数n,生成一个从1到n * n螺旋排列的矩阵,思路和昨天相似,可采用路径模拟法。


方法1:路径模拟

  1. 题目分析:由于输出矩阵大小固定,我们首先可以声明要返回的矩阵ret,大小为n * n。由于采用路径模拟,因此需要用两个变量row和col保存当前前进到的位置,然后需要用一个变量i保存当前位置要存放的值(i同时也表示已存元素的个数)。由于在碰到已访问过的元素时要改变方向,因此要用一个n * n矩阵来表示已被访问过的元素。由于方向一共有四种,故用一个变量directionIndex保存当前行进方向 。此外,直接在循环中用directionIndex来修改变量row和col的值要用到switch,程序冗余复杂,不利于后期维护,因此使用一个数组来表示四种状态下row和col的该变量。最后根据题意,row和col根据directionIndex的指向方向来移动变化,当碰到墙壁或者来到已访问过的位置时回退同时改变方向,一直移动直到移动n * n次为止,即可完成目标。

  2. 代码:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        vector<vector<int>> ret(n, vector<int>(n));
        vector<vector<bool>> visited(n, vector<bool>(n, false));
        int row = 0, col = 0;
        int directionIndex = 0;
        for (int i = 1; i <= n * n ; i++) {
            ret[row][col] = i;
            visited[row][col] = true;
            
            int nextRow = row + directions[directionIndex][0];
            int nextCol = col + directions[directionIndex][1];
            if (nextRow < 0 || nextRow >= n || nextCol < 0|| nextCol >= n || visited[nextRow][nextCol]) {
                directionIndex = (directionIndex + 1) % 4;
            }
            row += directions[directionIndex][0];
            col += directions[directionIndex][1];
        }
        return ret;
    }
};

方法2:按层填入

  1. 题目分析:还是用路径模拟的方法实现这个题目,区别在于利用到了螺旋矩阵的一个特点:每走一个螺旋对应到输出矩阵上就是一个外圈,每次都从左上角开始螺旋,且大圈包含小圈,各个圈没有重叠部分。因此可以将题目拆分成每完成一次螺旋后去掉已填入数字。

  2. 变量定义:首先需要定义主操作对象——二维矩阵,该矩阵同时也是函数的返回值。然后需要用一个变量i保存每次填入的数字。对于每层模拟,用lcol(left column)和rcol分别保存矩阵左边界和右边界,用lrow,rrow保存矩阵上边界和下边界。对于每步模拟,用row,col保存当前要填入的位置。

  3. 常量定义:无

  4. 程序步骤:定义边界为矩阵边界,i为1,row和col均为0。按层数对矩阵进行循环填写数字,循环开始时先重定义row和col的数值,每个循环填写一层数字,单次循环结束时调整上下左右边界,循环结束条件为左边界大于右边界或上边界大于下边界。另外循环结束后考虑特殊情况左边界等于右边界,此时直接赋值即可。

  5. 代码:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> ret(n, vector<int>(n,0));
        int i = 1;
        int lcol = 0, rcol = n - 1;
        int lrow = 0, rrow = n - 1;
        int row = 0, col = 0;
        while (lcol < rcol) {
            row = lrow, col = lcol;
            
            while (col < rcol) {
                ret[row][col] = i;
                col++;
                i++;
                
            } 
            
            while (row < rrow) {
                ret[row][col] = i;
                row++;
                i++;
            }
            while (col > lcol) {
                ret[row][col] = i;
                col--;
                i++;
            }
            while (row > lrow) {
                ret[row][col] = i;
                row--;
                i++;
            }
            lcol += 1; rcol -= 1;
            lrow += 1; rrow -= 1;
        } 
        if (lcol == rcol) {
            ret[lrow][lcol] = i;
        }
        return ret;
    }
};
posted @ 2021-03-16 15:29  wwtnb  阅读(119)  评论(0)    收藏  举报