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

螺旋矩阵的算法刷题

螺旋矩阵的算法刷题

本文主要涉及螺旋矩阵的算法
包括三个题目分别是

  1. 59. 螺旋矩阵 II
  2. 54. 螺旋矩阵 中等
  3. LCR 146. 螺旋遍历二维数组

文章目录

  • 螺旋矩阵的算法刷题
    • 一 、螺旋矩阵简单
      • 1.1 实现一(我认为这个方法更巧妙!!)
      • 1.2 实现二(经典方法--更加直观)
    • 二、螺旋矩阵 中等
      • 2.1 实现一(经典)
      • 2.2 实现二(精妙!!)
    • 三、螺旋遍历矩阵 简单

一 、螺旋矩阵简单

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix .

在这里插入图片描述

1.1 实现一(我认为这个方法更巧妙!!)

思路
采用了类似螺旋走位的方式进行填充,具体实现如下:

  1. 首先,定义一个n x n的二维数组res来存储结果。
  2. 初始化方向向量dx和dy,初始值分别为0和1,表示向右移动。
  3. 初始化坐标x和y,初始值都为0,表示从矩阵的左上角开始填充。
  4. 使用一个循环,从1到n * n遍历每个要填充的数字。
  5. 在每一步中,将当前位置的值设置为当前遍历的数字i,并根据当前方向向量(dx, dy)进行移动到下一个位置。
  6. 判断下一个位置是否已经被填充过,如果是,则表示已经到达边界,需要调转方向向量以继续填充;如果不是,则继续沿当前方向向量移动。
  7. 返回填充完成的二维数组res作为结果。

这样的算法可以确保填充的数字形成了一个螺旋状的矩阵。

C++代码实现

class Solution {
public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> matrix(n,vector<int>(n,0));//代表方向的向量变量 01--右 10--下 -1 0--左 0 -1 --上int dx=0,dy=1;//x,y表示当前坐标int x=0,y=0;//使用for进行循环,i表示当前值for(int i =1; i<=n*n;i++){matrix[x][y]=i;//**关键部分**if(matrix[(x+dx+n)%n][(y+dy+n)%n]!=0)//判断是否已经填充,如果已经填充则向量需要换方向{int temp = dy;dy=-dx;dx=temp;}x+=dx;y+=dy;}return matrix;    }
};

重要的是下面这段代码

 if(matrix[(x+dx+n)%n][(y+dy+n)%n]!=0)//判断是否已经填充,如果已经填充则向量需要换方向{int temp = dy;dy=-dx;dx=temp;}

这段代码是在判断当前位置的下一个位置是否已经被填充过。如果下一个位置已经被填充过,说明当前位置已经是当前层的最后一个位置,需要改变填充方向。

逐行解释这段代码:

  1. (x + dx + n) % n:这里计算了下一个位置的横坐标。由于是螺旋填充,因此下一个位置可能超出边界。使用 % n 可以将超出边界的情况转化为在边界内的情况。例如,当 x + dx 大于等于 n 时,超出了右边界,通过 % n 可以将其映射到左边界,从而形成循环填充。
  2. 同理,(y + dy + n) % n 计算了下一个位置的纵坐标。
  3. res[(x + dx + n) % n][(y + dy + n) % n] != 0:这个条件判断当前位置的下一个位置是否已经被填充过。如果下一个位置不等于0,说明已经被填充过。
  4. 如果下一个位置已经被填充过,则需要改变填充方向。通过交换 dxdy 实现了向下转向的功能。
  5. int tem = dy; dy = -dx; dx = tem;:这里使用了一个临时变量 tem,先将 dy 的值保存下来,然后将 dy 设置为 -dxdx 设置为 tem,实现了方向的转换。

在这里插入图片描述

总的来说,这段代码的作用是在当前位置的下一个位置已经被填充过时,改变填充方向,从而继续填充螺旋矩阵。

1.2 实现二(经典方法–更加直观)

一个常见的方法是按层次遍历,逐层填充螺旋矩阵。具体步骤如下:

  1. 初始化一个n x n的二维数组res,用于存储结果。
  2. 定义四个变量top、bottom、left、right,分别表示当前填充层的上下左右边界。
  3. 初始化这些边界值:top=0,bottom=n-1,left=0,right=n-1。
  4. 初始化一个变量num,表示当前要填充的数字,初始值为1。
  5. 在一个循环中,依次填充每一层的数字,直到所有位置都被填充为止。
    • 从左到右,将当前层的最上一行从left到right填充为num开始递增的数字,同时更新top的值使其向下移动一行。
    • 从上到下,将当前层的最右一列从top到bottom填充为num开始递增的数字,同时更新right的值使其向左移动一列。
    • 从右到左,将当前层的最下一行从right到left填充为num开始递增的数字,同时更新bottom的值使其向上移动一行。
    • 从下到上,将当前层的最左一列从bottom到top填充为num开始递增的数字,同时更新left的值使其向右移动一列。
    • 每填充完一行或一列后,将num递增。
  6. 当top > bottom 或 left > right时,表示所有位置都被填充完毕,退出循环。
  7. 返回填充完成的二维数组res作为结果。

这样的实现方法更直观清晰,容易理解和实现,并且效率也很高。

class Solution {
public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n, vector<int>(n, 0)); // 初始化结果矩阵为全零int top = 0, bottom = n - 1, left = 0, right = n - 1; // 初始化边界int num = 1; // 当前要填充的数字,初始为1while (true) {// 从左到右,填充最上一行for (int i = left; i <= right; ++i) {res[top][i] = num++;}if (++top > bottom) break; // 更新上边界,若超过下边界则退出// 从上到下,填充最右一列for (int i = top; i <= bottom; ++i) {res[i][right] = num++;}if (--right < left) break; // 更新右边界,若超过左边界则退出// 从右到左,填充最下一行for (int i = right; i >= left; --i) {res[bottom][i] = num++;}if (--bottom < top) break; // 更新下边界,若超过上边界则退出// 从下到上,填充最左一列for (int i = bottom; i >= top; --i) {res[i][left] = num++;}if (++left > right) break; // 更新左边界,若超过右边界则退出}return res;}
};

二、螺旋矩阵 中等

54. 螺旋矩阵 中等

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

在这里插入图片描述

2.1 实现一(经典)

class Solution {
public:vector<int> spiralOrder(vector<vector<int>>& matrix) {vector<int> ans;if (matrix.empty()) return ans;int m = matrix.size(); // 行数int n = matrix[0].size(); // 列数int top = 0, bottom = m - 1, left = 0, right = n - 1;while (top <= bottom && left <= right) {// 从左到右遍历上边界for (int j = left; j <= right; ++j) {ans.push_back(matrix[top][j]);}++top;// 从上到下遍历右边界for (int i = top; i <= bottom; ++i) {ans.push_back(matrix[i][right]);}--right;// 从右到左遍历下边界if (top <= bottom) { // 防止重复访问上一次遍历的元素for (int j = right; j >= left; --j) {ans.push_back(matrix[bottom][j]);}--bottom;}// 从下到上遍历左边界if (left <= right) { // 防止重复访问上一次遍历的元素for (int i = bottom; i >= top; --i) {ans.push_back(matrix[i][left]);}++left;}}return ans;}
};

按照螺旋顺序遍历二维矩阵。下面是对代码的详细解释:

  1. 首先,定义一个空的整数向量 ans 用于存储遍历结果。
  2. 如果输入的二维矩阵 matrix 为空,直接返回空的结果向量 ans
  3. 获取矩阵的行数 m 和列数 n,以及初始化四个边界变量 topbottomleftright
  4. 在一个循环中,不断遍历矩阵的边界元素,直到边界收缩到无效为止。
    • 从左到右遍历上边界,将上边界的元素依次加入结果向量 ans 中,并将 top 上移一行。
    • 从上到下遍历右边界,将右边界的元素依次加入结果向量 ans 中,并将 right 右移一列。
    • 从右到左遍历下边界,将下边界的元素依次加入结果向量 ans 中,并将 bottom 下移一行(注意要判断 top <= bottom,防止重复遍历)。
    • 从下到上遍历左边界,将左边界的元素依次加入结果向量 ans 中,并将 left 左移一列(注意要判断 left <= right,防止重复遍历)。
  5. 循环结束后,返回结果向量 ans

利用边界变量控制了螺旋顺序的遍历过程,实现了按照螺旋顺序遍历二维矩阵的功能。

2.2 实现二(精妙!!)

下面是一段Python代码:

def spiralOrder(self, matrix: List[List[int]]) -> List[int]:res = []while matrix:# 削头(第一层)res += matrix.pop(0)# 将剩下的逆时针转九十度,等待下次被削matrix = list(zip(*matrix))[::-1]return res

采用了不断“削头”的方式来实现。具体的步骤如下:

  1. 创建一个空列表 res 用于存储螺旋顺序遍历的结果。
  2. 使用 while matrix: 循环来遍历矩阵,直到矩阵为空。
  3. 在每一次循环中,先将矩阵的第一行(即第一层)添加到结果列表 res 中,然后将该行从矩阵中移除。
  4. 接着,将剩下的矩阵逆时针旋转 90 度(将其转置后再沿着竖直方向反转),以便下次循环时能够继续削头。
  5. 重复上述步骤直到矩阵为空。

这种方法的思路简洁,通过不断调整矩阵的结构来实现螺旋顺序遍历,避免了显式的控制遍历方向和边界条件的处理。

在实际代码中,matrix.pop(0) 用于削头,list(zip(*matrix))[::-1] 用于逆时针旋转矩阵。

如果是C++实现类似削头的效果:

#include <vector>class Solution {
public:vector<int> spiralOrder(vector<vector<int>>& matrix) {vector<int> res;while (!matrix.empty()) {// 削头(第一层)for (auto it = matrix[0].begin(); it != matrix[0].end(); ++it) {res.push_back(*it);}matrix.erase(matrix.begin()); // 删除第一行// 将剩下的逆时针转九十度,等待下次被削if (!matrix.empty()) {vector<vector<int>> new_matrix;for (int j = matrix[0].size() - 1; j >= 0; --j) {vector<int> column;for (int i = 0; i < matrix.size(); ++i) {column.push_back(matrix[i][j]);}new_matrix.push_back(column);}matrix = new_matrix;}}return res;}
};

三、螺旋遍历矩阵 简单

LCR 146. 螺旋遍历二维数组

上面这个题是企业题,同类型的题目可以多练习练习~

相关文章:

螺旋矩阵的算法刷题

螺旋矩阵的算法刷题 本文主要涉及螺旋矩阵的算法 包括三个题目分别是 59. 螺旋矩阵 II54. 螺旋矩阵 中等LCR 146. 螺旋遍历二维数组 文章目录 螺旋矩阵的算法刷题一 、螺旋矩阵简单1.1 实现一&#xff08;我认为这个方法更巧妙&#xff01;&#xff01;&#xff09;1.2 实现二&…...

蓝桥杯算法赛(二进制王国)

问题描述 二进制王国是一个非常特殊的国家&#xff0c;因为该国家的居民仅由 0 和 1 组成。 在这个国家中&#xff0c;每个家庭都可以用一个由 0 和 1 组成的字符串 S 来表示&#xff0c;例如 101、 000、 111 等。 现在&#xff0c;国王选了出 N 户家庭参加邻国的庆典…...

7.JDK下载和安装

文章目录 一、下载二、安装三、JDK的安装目录介绍 写JAVA代码不是随随便便能写的&#xff0c;我们得先做一点准备工作。例如&#xff0c;我们平时想要玩一把游戏&#xff0c;就需要先下载、安装才能玩游戏。JAVA也是一样的&#xff0c;也是需要下载并安装相关的软件&#xff0c…...

Java序列化之Jackson详解

文章目录 1 Jackson1.1 Jackson简介1.2 为什么选择Jackson1.3 Jackson的基本功能1.3.1 将Java对象转换为JSON字符串&#xff08;序列化&#xff09;1.3.2 将JSON字符串转换为Java对象&#xff08;反序列化&#xff09; 1.4 Jackson库主要方法1.5 使用Jackson基本步骤1.5.1 添加…...

深入Facebook的世界:探索数字化社交的无限可能性

引言 随着数字化时代的到来&#xff0c;社交媒体平台已经成为了人们日常生活中不可或缺的一部分&#xff0c;而其中最为突出的代表之一便是Facebook。作为全球最大的社交媒体平台之一&#xff0c;Facebook不仅仅是一个社交网络&#xff0c;更是一个数字化社交的生态系统&#…...

HTML 怎么解决上下标问题呢?

当我们阅读内容时&#xff0c;经常会遇到特殊格式的文本&#xff0c;如化学式的下标和数学公式的上标&#xff0c;sub 标签和sup 标签就是用来解决这个问题的。 1. 基础语法 什么是 sub 和sup标签 sub 标签用于定义下标文本&#xff0c;而 sup 标签用于定义上标文本。 这些…...

题目 2880: 计算鞍点

题目描述: 给定一个5*5的矩阵&#xff0c;每行只有一个最大值&#xff0c;每列只有一个最小值&#xff0c;寻找这个矩阵的鞍点。 鞍点指的是矩阵中的一个元素&#xff0c;它是所在行的最大值&#xff0c;并且是所在列的最小值。 例如&#xff1a;在下面的例子中&#xff08;第…...

前端Web移动端学习day05

移动 Web 第五天 响应式布局方案 媒体查询Bootstrap框架 响应式网页指的是一套代码适配多端&#xff0c;一套代码适配各种大小的屏幕。 共有两种方案可以实现响应式网页&#xff0c;一种是媒体查询&#xff0c;另一种是使用bootstrap框架。 01-媒体查询 基本写法 max-wid…...

蚂蚁庄园今日答案

蚂蚁庄园是一款爱心公益游戏&#xff0c;用户可以通过喂养小鸡&#xff0c;产生鸡蛋&#xff0c;并通过捐赠鸡蛋参与公益项目。用户每日完成答题就可以领取鸡饲料&#xff0c;使用鸡饲料喂鸡之后&#xff0c;会可以获得鸡蛋&#xff0c;可以通过鸡蛋来进行爱心捐赠。其中&#…...

深度学习中的随机种子random_seed

在深度学习中&#xff0c;random_seed是一个用于控制随机过程的种子值。这个种子值用于初始化随机数生成器&#xff0c;从而确保在多次实验中&#xff0c;涉及随机性的步骤能够产生一致的结果。这对于实验的可重复性、调试以及结果对比都是至关重要的。 具体来说&#xff0c;深…...

【项目技术介绍篇】若依管理系统功能介绍

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…...

Maximum Sum(贪心策略,模运算,最大子段和)

文章目录 题目描述输入格式输出格式样例输入1样例输出1样例输入2样例输出2提交链接提示 解析参考代码 题目描述 你有一个由 n n n 个整数组成的数组 a a a 。 你要对它进行 k k k 次操作。其中一个操作是选择数组 a a a 的任意连续子数组(可能为空)&#xff0c;并在数组的…...

Gartner 公布 2024 年八大网络安全预测

近日&#xff0c;Gartner 安全与风险管理峰会在悉尼举行&#xff0c;旨在探讨网络安全的发展前景。 本次峰会&#xff0c;Gartner 公布了 2024 年及以后的八大网络安全预测。 Gartner 研究总监 Deepti Gopal 表示&#xff0c;随着 GenAI 的不断发展&#xff0c;一些长期困扰网…...

《每天十分钟》-红宝书第4版-对象、类与面向对象编程(六)

盗用构造函数 上节提到原型包含引用值导致的继承问题&#xff0c;为了解决这种问题&#xff0c;一种叫作“盗用构造函数”&#xff08;constructor stealing&#xff09;的技术在开发社区流行起来&#xff08;这种技术有时也称作“对象伪装”或“经典继承”&#xff09;。基本…...

Ubuntu Desktop Server - user 用户与 root 用户切换

Ubuntu Desktop Server - user 用户与 root 用户切换 1. user 用户与 root 用户切换2. root 用户与 user 用户切换References 1. user 用户与 root 用户切换 strongforeverstrong:~$ strongforeverstrong:~$ sudo su [sudo] password for strong: rootforeverstrong:/home/s…...

SQL Server事务复制操作出现的错误 进程无法在“xxx”上执行sp_replcmds

SQL Server事务复制操作出现的错误 进程无法在“xxx”上执行“sp_replcmds” 无法作为数据库主体执行&#xff0c;因为主体 "dbo" 不存在、无法模拟这种类型的主体&#xff0c;或您没有所需的权限...

学点儿Java_Day12_IO流

1 IO介绍以及分类 IO: Input Output 流是一组有顺序的&#xff0c;有起点和终点的字节集合&#xff0c;是对数据传输的总称或抽象。即数据在两设备间的传输称为流&#xff0c;流的本质是数据传输&#xff0c;根据数据传输特性将流抽象为各种类&#xff0c;方便更直观的进行数据…...

【python】python编程初探1----python中的基本语法,标识符,关键字,注释,多行书写,代码缩进,语句块,模块等

欢迎来CILMY23的博客喔&#xff0c;本篇为【python】python编程初探1----python中的基本语法&#xff0c;标识符&#xff0c;关键字&#xff0c;注释&#xff0c;多行书写&#xff0c;代码缩进&#xff0c;语句块&#xff0c;模块&#xff0c;感谢观看&#xff0c;支持的可以给…...

牛客周赛 Round 38

牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com) A-小红的正整数自增_牛客周赛 Round 38 (nowcoder.com) 取出最后一位判断即可 #include<iostream> #include<algorithm> #include<vector> #include<set> #include…...

漏洞扫描操作系统识别技术原理

漏洞扫描过程中&#xff0c;操作系统识别技术是至关重要的一步&#xff0c;因为它有助于扫描器针对性地选择适用的漏洞检测规则&#xff0c;提高扫描的准确性和效率。以下是漏洞扫描中操作系统识别技术的主要原理&#xff1a; **1. **TCP/IP 协议栈指纹识别** **原理**&#…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

Visual Studio Code 扩展

Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后&#xff0c;命令 changeCase.commands 可预览转换效果 EmmyLua…...