论螺旋矩阵

螺旋矩阵题型总结。我刷了几道螺旋矩阵相关的题目,这里我们介绍一下一些常见的解法。

螺旋矩阵

方形矩阵

当我们遇到n*n的方形矩阵时,可以用一种特殊的解法来遍历实现,以下面这道题为例:

59. 螺旋矩阵 II

我们可以定义几个变量用来控制遍历的行为:

  • startX:每次循环的起点的行数

  • startY:每次循环的起点的列数

  • offset:每循环一圈,用偏移量表现

vector<vector<int>> generateMatrix(int n) {vector<vector<int>> ans(n,vector<int>(n,0));int offset = 1 , startX = 0 , startY = 0;int val = 1;int i,j;for(int k=0;k<n/2;k++){     //循环次数就是圈数for(j=startY;j<n-offset;j++)    //左上->右上(从此以下都是左闭右开)ans[startX][j] = val++;for(i=startX;i<n-offset;i++)    //右上->右下ans[i][j] = val++;for(;j>startY;j--)              //右下->左下    ans[i][j] = val++;for(;i>startX;i--)              //左下->右上ans[i][j] = val++;startX++;startY++;offset++;   //实际上更新offset就是在更新每次循环的边界(缩小)}if (n&1){   //如果矩阵的边长为奇数,最中间的值会没法遍历到ans[offset-1][offset-1] = val;}return ans;}
};

同时还可以将方形矩阵视作一种特殊的矩形矩阵,以下对矩形矩阵的所有解法对方形都适用。

矩形矩阵

有时候我们会发现矩阵是矩形的,或者只有一层,这个时候就需要用几个通用的方法,来实现。例题:

LCR 146. 螺旋遍历二维数组

54. 螺旋矩阵

2326. 螺旋矩阵 IV

模拟路径法

我们先分析我们的转向条件:(1)当前进的方向上碰到了边界(2)当前进的方向上是已经走过的路径

第一个条件比较好解决,第二条件我们需要维护一个和数组相同大小的矩阵,走过的路线我们设置为true,没走过的设置为false.

由于我们的转向动作是有序的,是顺时针,所以我们可以使用一个数组来存储我们的方向。当到达转向条件时,设置成下一个转向动作。

vector<int> spiralArray(vector<vector<int>>& array) {if(array.empty()||array[0].empty()) //判断数组是否为空,注意先后顺序,array[0]在array为空时是不能访问的return {};int row = array.size();int col = array[0].size();int total = row*col;vector<vector<bool>> use(row,vector<bool>(col,0));  //路径表vector<int> ans(total,0);vector<vector<int>> direction{{0,1},{1,0},{0,-1},{-1,0}};   //方向表(顺时针)int directionIdx = 0;   //方向表索引int i=0,j=0;for(int k=0;k<total;k++){ans[k] = array[i][j];use[i][j] = true;int ni = i + direction[directionIdx][0];    //预更新iint nj = j + direction[directionIdx][1];    //预更新jif(ni<0||ni>=row||nj<0||nj>=col||use[ni][nj]==true){    //根据预更新状态判断转向条件directionIdx = (directionIdx+1)%4;  //转向则把方向索引设置到下一位}//实际更新i = i + direction[directionIdx][0];j = j + direction[directionIdx][1];}return ans;}

层级遍历法(边界收缩)

这个和刚刚用来解决方形矩阵的方法是相同的,只不过更新方式和更新条件要更加复杂。

一开始先设定好边界,当移动到边界的时候就转向,然后收缩边界。这样的好处在于我们不用再特意维护一个数组来判断路径是否被走过 了。因为走过的路径被我们收缩了,所以就不用在考虑。只需要在边界做检测就好了。

vector<vector<int>> spiralMatrix(int m, int n, ListNode* head) {vector<vector<int>> ans(m,vector<int>(n,-1));int top = 0;    int bottom = m-1;   //-1是因为索引和实际位置的差值int left = 0;int right = n-1;while(left<=right&&top<=bottom){    //如果相等就说明,边界收缩了,遍历结束了for(int i=left;i<=right;i++)    ans[top][i] = val;top++;                          //左上->右上 top边界收缩for(int i=top;i<=bottom;i++)ans[i][right] = val;right--;                        //右上->右下 right边界收缩for(int i=right;i>=left;i--)ans[bottom][i] = val;bottom--;                       //右下->左下 bottom边界收缩for(int i=bottom;i>=top;i--)ans[i][left] = val;left++;                         //左下->右上 left边界收缩}return ans;}

螺旋生成矩阵

这个算是一个小特例,大多数题目是给你一个矩阵让你去螺旋遍历,但是有的题目需要你自己螺旋生成一个矩阵。我们看到下面的例题:

885. 螺旋矩阵 III

image.png

这道题需要我们形成一个螺旋的路径,然后返回矩形内的位置的坐标。难点在于这个螺旋路径的生成,因为转向的条件和每次前进的步长综合考虑起来条件会非常的复杂。下面的话给出两种方法。

边界扩展法

和我们之前所做的边界收缩相反,我们先界定好边界,然后每次转向时宽展这个方向上的边界。通过这种方式来动态的生成一个螺旋的路径

const int DIR[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
vector<vector<int>> spiralMatrixIII(int rows, int cols, int rStart, int cStart) {vector<vector<int>> ans;int total = rows*cols;int num = 1;int i = rStart,j = cStart;  //令i,j记录路径的实时位置int left = cStart - 1,right = cStart + 1,top = rStart - 1,bottom = rStart + 1;  //确定边界int dir=0;  //记录方向while(num <= total){if(i>=0&&i<rows&&j>=0&&j<cols){ //当路径到达矩阵内部时,记录当前位置ans.push_back({i,j});num++;}if(dir==0&&j==right){   //如果向右移动触碰右边界dir+=1;             //则转向right++;            //并拓展右边界}else if(dir==1&&i==bottom){    //如果向下移动触碰下边界dir+=1;                     //则转向bottom++;                   //并拓展下边界}else if(dir==2&&j==left){      //...dir+=1;left--;}else if(dir==3&&i==top){       //...dir=0;top--;}i += DIR[dir][0];       //根据方向来更新位置j += DIR[dir][1];}return ans;}

规律法

我们可以观察螺线路径的一个显著规律:每转向两次会更新一次前进的步长

const int DIR[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
vector<vector<int>> spiralMatrixIII(int R, int C, int r0, int c0) {int num=0;int dir=0;int run=2;  //步长计数器vector<vector<int>> ans;
​while(num < R * C){for(int i = 0; i < run / 2; i ++){   //遍历步长,每转两下就会增加一步if(r0 >= 0 && r0 < R && c0 >= 0 && c0 < C)ans.push_back({r0, c0}), ++ num;r0 += DIR[dir][0];c0 += DIR[dir][1];}pos = (pos + 1) % 4;    //每遍历一次步长,就转向run++;      //利用取整的性质,每转向两次才会增加一次步长}return ans;}

总结

螺旋矩阵的关键在于边界的检测和变换,还有转向条件的判断。比较简单。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91763.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数学金融与金融工程:学科差异与选择指南

在金融领域的学习中&#xff0c;数学金融与金融工程常被混淆。两者虽同属 “金融 量化” 交叉方向&#xff0c;但在研究侧重、培养路径上有显著区别。结合学科特点与行业实践&#xff0c;帮大家理清两者的核心差异&#xff0c;以便更精准地选择方向。一、核心差异&#xff1a;…

包管理工具npm cnpm yarn的使用

包管理工具 1. 什么是包管理工具? 包管理工具是用于管理和安装 Node.js 项目依赖的工具。它们提供了一种结构化的方式来管理项目的依赖关系,使得项目的依赖管理变得更加便捷和可靠。 2. 常见的包管理工具有哪些? npm(Node Package Manager):是 Node.js 的默认包管理工…

网络基础13--链路聚合技术

一、链路聚合概述定义将多条物理链路捆绑为一条逻辑链路&#xff0c;提升带宽与可靠性。2. 应用场景交换机/路由器/服务器之间的互联&#xff0c;支持二层&#xff08;数据链路层&#xff09;和三层&#xff08;网络层&#xff09;聚合。二、核心作用增加带宽聚合链路的总带宽 …

一文讲清楚React性能优化

文章目录一文讲清楚React性能优化1. React性能优化概述2. React性能优化2.1 render优化2.2 较少使用内联函数2.3 使用React Fragments避免额外标记2.4 使用Immutable上代码2.5 组件懒加载2.6 服务端渲染2.7 其他优化手段一文讲清楚React性能优化 1. React性能优化概述 React通…

3.0 - 指针-序列化

一、关于Serialize的使用 可以使用该指令临时将用户程序的多个结构化数据项保存到缓冲区中(最好位于全局数据块中)。用于保存转换后数据的存储区的数据类型必需为 ARRAY of BYTE 或 ARRAY of CHAR 相当于把一个struct或其他自定义类型变成一个字节数组。 比如我有好几个结构体…

【论文精读】基于共识的分布式量子分解算法用于考虑最优传输线切换的安全约束机组组合

本次分析的论文《Consensus‐Based Distributed Quantum Decomposition Algorithm for Security‐Constrained Unit Commitment Considering Optimal Transmission Switching》于2025年6月25日在《Advanced Quantum Technologies》期刊上公开发表。本文提出了一个新的基于共识的…

MyBatis-Flex代码生成

引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok<…

知网论文批量下载pdf格式论文,油猴脚本

任务描述 今天收到一个任务&#xff0c;在知网上&#xff0c;把一位专家所有的论文全都下载下来&#xff0c;要保存为PDF格式。 知网不支持批量导出PDF格式论文。一个一个下载PDF&#xff0c;太繁琐了。 解决方案&#xff1a;找到一个油猴脚本&#xff0c;这个脚本可以从知网…

低代码平台:驱动项目管理敏捷开发新范式

随着企业数字化转型加速&#xff0c;项目管理系统已从单一任务跟踪工具到集成流程自动化、资源调度、跨团队协作与风险监控的综合平台&#xff0c;项目管理系统的功能复杂度持续提升。然而&#xff0c;根据Gartner 2024年研究报告显示&#xff0c;约60%的项目管理系统因未能有效…

图机器学习(11)——链接预测

图机器学习&#xff08;11&#xff09;——链接预测0. 链接预测1. 基于相似性的方法1.1 基于指标的方法1.2 基于社区的方法2. 基于嵌入的方法0. 链接预测 链接预测 (link prediction)&#xff0c;也称为图补全&#xff0c;是处理图时常见的问题。具体而言&#xff0c;给定一个…

简单2步配置CadenceSkill开发编辑器,支持关键字高亮

Cadence 使用过程中难免会与skill打交道&#xff0c;有时候网上找到的开源skill&#xff0c;想要查看或者编辑一下&#xff0c;常规的txt编辑器没有关键字高亮&#xff0c;看起来极为不方便。 利用Sublime Text可以很快速配置出支持skill关键字高亮的编辑器。 一、安装 Sublime…

Leetcode刷题营第三十三题:对称二叉树

101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示&#xff1a;…

day055-Dockerfile与常用指令

文章目录0. 老男孩思想-女性的第一需求1. Dockerfile1.1 Dockerfile的基本结构1.2 案例-制作小鸟飞飞镜像1.2.1 编写Dockerfile文件1.2.2 构建镜像1.2.3 启动容器1.3 Dockerfile常用指令1.4 面试题&#xff1a;Dockerfile中CMD和ENTRYPOINT的区别&#xff1f;1.5 案例-制作zrlo…

Spring Boot 应用优雅停机与资源清理:深入理解关闭钩子

在开发和部署 Spring Boot 应用程序时&#xff0c;除了关注其启动和运行&#xff0c;理解如何实现**优雅停机&#xff08;Graceful Shutdown&#xff09;**也同样至关重要。优雅停机意味着在应用程序关闭时&#xff0c;能够有序地释放资源、完成正在进行的任务&#xff0c;并避…

淘宝扭蛋机小程序开发:重构电商娱乐化体验的新范式

在电商行业同质化竞争加剧的当下&#xff0c;消费者对购物体验的期待已从“功能满足”转向“情感共鸣”。淘宝扭蛋机小程序凭借“盲盒式随机奖励游戏化交互”的创新模式&#xff0c;成为撬动年轻用户消费力的新支点。其开发逻辑不仅是对传统电商的升级&#xff0c;更是对“娱乐…

YOLO演变史(一)

在YOLOV1发布后&#xff0c;作者并没有满足于此&#xff0c;而是持续对YOLO进行了改进。 YOLOV2&#xff1a;Better, Faster, Stronger YOLOv2&#xff08;又称YOLO9000&#xff09;发表于2017年CVPR&#xff0c;是YOLO系列的第二代版本。其论文标题“Better, Faster, Stronger…

专题:2025智能体研究报告|附70份报告PDF、原数据表汇总下载

原文链接&#xff1a;https://tecdat.cn/?p43035 智能体正在改写商业规则&#xff1a;某城商行的智能客服用公有云部署&#xff0c;把单笔交互成本从5.7元砍到1.2元&#xff0c;投诉率直降42%&#xff08;《赛迪智库&#xff1a;2025全球智能体进展报告》P24&#xff09;&…

Axios 完整功能介绍和完整示例演示

Axios 是一个基于 Promise 的现代化 HTTP 客户端库&#xff0c;用于浏览器和 Node.js 环境。它提供了简洁的 API 和强大的功能&#xff0c;是前端开发中最常用的网络请求工具之一。核心功能 浏览器 & Node.js 双平台支持 浏览器中使用 XMLHttpRequestNode.js 中使用 http 模…

math.h函数

math.c函数作用 1. 基本三角函数&#xff08;参数为弧度&#xff09; sin(double x)&#xff1a;计算正弦值。cos(double x)&#xff1a;计算余弦值。tan(double x)&#xff1a;计算正切值。asin(double x)&#xff1a;反正弦&#xff08;返回值范围&#xff1a;[-π/2, π/2]&…

在Next.js里玩转pdf预览

1.背景在项目开发中&#xff0c;pdf预览是一个很常见的业务。各大公司为了保护自己的知识产权&#xff0c;也会对pdf预览进行限制&#xff0c;比如&#xff1a;不允许下载、打印&#xff0c;不允许提取文字等等。要想在实现预览功能的基础上还要附加这些限制&#xff0c;有很多…