当前位置: 首页 > article >正文

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)。该方法与上述方法比,只是使用了四个表示方位的变量,因此空间复杂度为常量级别


http://www.kler.cn/a/446909.html

相关文章:

  • Linux系统的阻塞方式和非阻塞方式是什么意思?
  • Nginx的stream模块代理四层协议TCP的流量转发
  • PCL点云库入门——PCL库中点云数据拓扑关系之K-D树(KDtree)
  • 投标心态:如何在“标海战术”中保持清醒的头脑?
  • 电商数据流通的未来:API接口的智能化与自动化趋势
  • AI的进阶之路:从机器学习到深度学习的演变(二)
  • 华为OD --- 流浪地球
  • Golang uint 类型溢出问题
  • LLaMA-Factory 单卡3080*2 deepspeed zero3 微调Qwen2.5-7B-Instruct
  • 2023年西南大学数学建模C题天气预报解题全过程文档及程序
  • 多态中虚函数调用问题
  • jvm栈帧结构
  • 前端关于pptxgen.js个人使用介绍
  • Linux setfacl 命令详解
  • STM32 高级 物联网通信之CAN通讯
  • 华为笔记本之糟糕的体验
  • 鸿蒙项目云捐助第十四讲云函数的初步使用
  • MFC/C++学习系列之简单记录5
  • c++数据结构算法复习基础--12--排序算法-常见笔试面试问题
  • go 适配windows和linux获取文件创建时间的方法(跨平台的方法不一致的解决问题)
  • RabbitMQ如何构建集群?
  • 华为云检查服务器状态
  • 遇见物联网
  • day4:tomcat—maven-jdk
  • MySQL结构的主要组成
  • 分布式数据存储基础与HDFS操作实践