leetcode之hot100---54螺旋矩阵(C++)

思路一:模拟

模拟螺旋矩阵的路径,路径超出界限,顺时针旋转,使用一个数组记录当前数字是否被访问到,直到所有的数字全部被访问

class Solution {
    //一个静态的常量数组,用于标记螺旋矩阵的移动方向(行列变化)
    //{0, 1}:表示向右移动一格(x 不变,y+1)。
    //{1, 0}:表示向下移动一格(x+1,y 不变)。
    //{0, -1}:表示向左移动一格(x 不变,y-1)。
    //{-1, 0}:表示向上移动一格(x-1,y 不变)
    static constexpr int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        //判断矩阵行列是否为空,如果为空则返回空值
        if(matrix.size() == 0 || matrix[0].size() == 0){
            return {};
        }
        vector<int> ans;
        int m = matrix.size();//行最大
        int n = matrix[0].size();//列最大
        
        
        //数字是否已经被访问的标签数组
        vector<vector<bool>> visited(m, vector<bool>(n,false));
        //记录存入答案数组中的个数
        int col = 0, row = 0;//螺旋矩阵的起始路径
        //当前方向的索引,可以取0-3,分别对应directions数组中的四个方位
        int direction_index = 0;
        for(int count = 0; count < m * n; count++){
            ans.push_back(matrix[row][col]);//将矩阵中的数字存入结果中
            visited[row][col] = true;//标记已访问的数字
            //计算下一位置
            //行变化列不动,取directions数组中的x坐标
            //列变化行不动,取directions数组中的y坐标
            int next_row = row + directions[direction_index][0];
            int next_col = col + directions[direction_index][1];
            // 判断是否需要改变移动方向(越界或已访问)
            if(next_row < 0 || next_row >= m || next_col < 0 || next_col >= n || visited[next_row][next_col]){
                direction_index = (direction_index + 1) % 4;
            }
            //根据判断的方向进行移动
            row += directions[direction_index][0];
            col += directions[direction_index][1];
        }
        return ans;
    }
};

constexpr的使用是告诉大家该数组为一个常量表达式,在编译的过程中其值不会改变

这个方法的关键在于写出这个方向数组,我们平时做的题目中如果涉及到处理二维网格上的移动问题,例如:遍历上下左右四个方向执行 BFS/DFS 等搜索算法模拟迷宫、棋盘等问题中的移动逻辑,都可以使用这个方向数组

  • 时间复杂度:O(mn)

  • 空间复杂度:O(mn)

思路二:按层模拟

与上述方法不同的是,这个方法更像是分治的思路,将顺时针矩阵分解成不同层的矩阵,然后又把不同层分解成从左至右、从上至下、从右至左、从下至上四个方向,详解如图所示:

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        //矩阵行或者列为空,说明矩阵为空,则返回空值
        if(matrix.size() == 0 || matrix[0].size() == 0){
            return {};
        }
        vector<int> ans;
        int m = matrix.size();//行最大
        int n = matrix[0].size();//列最大
                
        int top = 0, bottom = m - 1;
        int left = 0, right = n - 1;
        while(left <= right && top <= bottom){
            //把每一层的数从左至右放入结果数组中
            for(int col = left; col <= right; col++){
                ans.push_back(matrix[top][col]);//将矩阵中的数字存入结果中
            }
            
            //把每一层的数从上至下放入结果数组中
            for(int row = top + 1; row <= bottom; row++){
                ans.push_back(matrix[row][right]);//将矩阵中的数字存入结果中
            }
            
            if(left < right && top < bottom){
                //把每一层的数从右至左放入结果数组中
                for(int col = right - 1; col > left; col--){
                    ans.push_back(matrix[bottom][col]);//将矩阵中的数字存入结果中
                }
                
                //把每一层的数从下至上放入结果数组中
                for(int row = bottom; row > top; row--){
                    ans.push_back(matrix[row][left]);//将矩阵中的数字存入结果中
                }
                
            }
            top++;
            right--;
            bottom--;
            left++;
        }
       
        return ans;
    }
};

基于上述思想,可以自行选择每一层四个方向的截止位置(也就是每一方向存入数组的最后一个数)和起始位置(也就是每一方向存入数组的第一个数),比如从左至右的截止点可以是[top, right],也可以是[top,right - 1],同时,从上至下的起始点也可以是[top + 1, right],也可以是[top, right]只要每一方向的起始点和上一方向的截止点保证连续即可

  • 时间复杂度:O(mn)

  • 空间复杂度:O(1)。该方法与上述方法比,只是使用了四个表示方位的变量,因此空间复杂度为常量级别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值