螺旋矩阵的算法刷题
螺旋矩阵的算法刷题
本文主要涉及螺旋矩阵的算法
包括三个题目分别是
- 59. 螺旋矩阵 II
- 54. 螺旋矩阵 中等
- LCR 146. 螺旋遍历二维数组
文章目录
- 螺旋矩阵的算法刷题
- 一 、螺旋矩阵简单
- 1.1 实现一(我认为这个方法更巧妙!!)
- 1.2 实现二(经典方法--更加直观)
- 二、螺旋矩阵 中等
- 2.1 实现一(经典)
- 2.2 实现二(精妙!!)
- 三、螺旋遍历矩阵 简单
一 、螺旋矩阵简单
59. 螺旋矩阵 II
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix .

1.1 实现一(我认为这个方法更巧妙!!)
思路:
采用了类似螺旋走位的方式进行填充,具体实现如下:
- 首先,定义一个n x n的二维数组res来存储结果。
- 初始化方向向量dx和dy,初始值分别为0和1,表示向右移动。
- 初始化坐标x和y,初始值都为0,表示从矩阵的左上角开始填充。
- 使用一个循环,从1到n * n遍历每个要填充的数字。
- 在每一步中,将当前位置的值设置为当前遍历的数字i,并根据当前方向向量(dx, dy)进行移动到下一个位置。
- 判断下一个位置是否已经被填充过,如果是,则表示已经到达边界,需要调转方向向量以继续填充;如果不是,则继续沿当前方向向量移动。
- 返回填充完成的二维数组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;}
这段代码是在判断当前位置的下一个位置是否已经被填充过。如果下一个位置已经被填充过,说明当前位置已经是当前层的最后一个位置,需要改变填充方向。
逐行解释这段代码:
(x + dx + n) % n:这里计算了下一个位置的横坐标。由于是螺旋填充,因此下一个位置可能超出边界。使用% n可以将超出边界的情况转化为在边界内的情况。例如,当x + dx大于等于n时,超出了右边界,通过% n可以将其映射到左边界,从而形成循环填充。- 同理,
(y + dy + n) % n计算了下一个位置的纵坐标。 res[(x + dx + n) % n][(y + dy + n) % n] != 0:这个条件判断当前位置的下一个位置是否已经被填充过。如果下一个位置不等于0,说明已经被填充过。- 如果下一个位置已经被填充过,则需要改变填充方向。通过交换
dx和dy实现了向下转向的功能。 int tem = dy; dy = -dx; dx = tem;:这里使用了一个临时变量tem,先将dy的值保存下来,然后将dy设置为-dx,dx设置为tem,实现了方向的转换。

总的来说,这段代码的作用是在当前位置的下一个位置已经被填充过时,改变填充方向,从而继续填充螺旋矩阵。
1.2 实现二(经典方法–更加直观)
一个常见的方法是按层次遍历,逐层填充螺旋矩阵。具体步骤如下:
- 初始化一个n x n的二维数组res,用于存储结果。
- 定义四个变量top、bottom、left、right,分别表示当前填充层的上下左右边界。
- 初始化这些边界值:top=0,bottom=n-1,left=0,right=n-1。
- 初始化一个变量num,表示当前要填充的数字,初始值为1。
- 在一个循环中,依次填充每一层的数字,直到所有位置都被填充为止。
- 从左到右,将当前层的最上一行从left到right填充为num开始递增的数字,同时更新top的值使其向下移动一行。
- 从上到下,将当前层的最右一列从top到bottom填充为num开始递增的数字,同时更新right的值使其向左移动一列。
- 从右到左,将当前层的最下一行从right到left填充为num开始递增的数字,同时更新bottom的值使其向上移动一行。
- 从下到上,将当前层的最左一列从bottom到top填充为num开始递增的数字,同时更新left的值使其向右移动一列。
- 每填充完一行或一列后,将num递增。
- 当top > bottom 或 left > right时,表示所有位置都被填充完毕,退出循环。
- 返回填充完成的二维数组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;}
};
按照螺旋顺序遍历二维矩阵。下面是对代码的详细解释:
- 首先,定义一个空的整数向量
ans用于存储遍历结果。 - 如果输入的二维矩阵
matrix为空,直接返回空的结果向量ans。 - 获取矩阵的行数
m和列数n,以及初始化四个边界变量top、bottom、left和right。 - 在一个循环中,不断遍历矩阵的边界元素,直到边界收缩到无效为止。
- 从左到右遍历上边界,将上边界的元素依次加入结果向量
ans中,并将top上移一行。 - 从上到下遍历右边界,将右边界的元素依次加入结果向量
ans中,并将right右移一列。 - 从右到左遍历下边界,将下边界的元素依次加入结果向量
ans中,并将bottom下移一行(注意要判断top <= bottom,防止重复遍历)。 - 从下到上遍历左边界,将左边界的元素依次加入结果向量
ans中,并将left左移一列(注意要判断left <= right,防止重复遍历)。
- 从左到右遍历上边界,将上边界的元素依次加入结果向量
- 循环结束后,返回结果向量
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
采用了不断“削头”的方式来实现。具体的步骤如下:
- 创建一个空列表
res用于存储螺旋顺序遍历的结果。 - 使用
while matrix:循环来遍历矩阵,直到矩阵为空。 - 在每一次循环中,先将矩阵的第一行(即第一层)添加到结果列表
res中,然后将该行从矩阵中移除。 - 接着,将剩下的矩阵逆时针旋转 90 度(将其转置后再沿着竖直方向反转),以便下次循环时能够继续削头。
- 重复上述步骤直到矩阵为空。
这种方法的思路简洁,通过不断调整矩阵的结构来实现螺旋顺序遍历,避免了显式的控制遍历方向和边界条件的处理。
在实际代码中,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 实现一(我认为这个方法更巧妙!!)1.2 实现二&…...
蓝桥杯算法赛(二进制王国)
问题描述 二进制王国是一个非常特殊的国家,因为该国家的居民仅由 0 和 1 组成。 在这个国家中,每个家庭都可以用一个由 0 和 1 组成的字符串 S 来表示,例如 101、 000、 111 等。 现在,国王选了出 N 户家庭参加邻国的庆典…...
7.JDK下载和安装
文章目录 一、下载二、安装三、JDK的安装目录介绍 写JAVA代码不是随随便便能写的,我们得先做一点准备工作。例如,我们平时想要玩一把游戏,就需要先下载、安装才能玩游戏。JAVA也是一样的,也是需要下载并安装相关的软件,…...
Java序列化之Jackson详解
文章目录 1 Jackson1.1 Jackson简介1.2 为什么选择Jackson1.3 Jackson的基本功能1.3.1 将Java对象转换为JSON字符串(序列化)1.3.2 将JSON字符串转换为Java对象(反序列化) 1.4 Jackson库主要方法1.5 使用Jackson基本步骤1.5.1 添加…...
深入Facebook的世界:探索数字化社交的无限可能性
引言 随着数字化时代的到来,社交媒体平台已经成为了人们日常生活中不可或缺的一部分,而其中最为突出的代表之一便是Facebook。作为全球最大的社交媒体平台之一,Facebook不仅仅是一个社交网络,更是一个数字化社交的生态系统&#…...
HTML 怎么解决上下标问题呢?
当我们阅读内容时,经常会遇到特殊格式的文本,如化学式的下标和数学公式的上标,sub 标签和sup 标签就是用来解决这个问题的。 1. 基础语法 什么是 sub 和sup标签 sub 标签用于定义下标文本,而 sup 标签用于定义上标文本。 这些…...
题目 2880: 计算鞍点
题目描述: 给定一个5*5的矩阵,每行只有一个最大值,每列只有一个最小值,寻找这个矩阵的鞍点。 鞍点指的是矩阵中的一个元素,它是所在行的最大值,并且是所在列的最小值。 例如:在下面的例子中(第…...
前端Web移动端学习day05
移动 Web 第五天 响应式布局方案 媒体查询Bootstrap框架 响应式网页指的是一套代码适配多端,一套代码适配各种大小的屏幕。 共有两种方案可以实现响应式网页,一种是媒体查询,另一种是使用bootstrap框架。 01-媒体查询 基本写法 max-wid…...
蚂蚁庄园今日答案
蚂蚁庄园是一款爱心公益游戏,用户可以通过喂养小鸡,产生鸡蛋,并通过捐赠鸡蛋参与公益项目。用户每日完成答题就可以领取鸡饲料,使用鸡饲料喂鸡之后,会可以获得鸡蛋,可以通过鸡蛋来进行爱心捐赠。其中&#…...
深度学习中的随机种子random_seed
在深度学习中,random_seed是一个用于控制随机过程的种子值。这个种子值用于初始化随机数生成器,从而确保在多次实验中,涉及随机性的步骤能够产生一致的结果。这对于实验的可重复性、调试以及结果对比都是至关重要的。 具体来说,深…...
【项目技术介绍篇】若依管理系统功能介绍
作者介绍:本人笔名姑苏老陈,从事JAVA开发工作十多年了,带过大学刚毕业的实习生,也带过技术团队。最近有个朋友的表弟,马上要大学毕业了,想从事JAVA开发工作,但不知道从何处入手。于是࿰…...
Maximum Sum(贪心策略,模运算,最大子段和)
文章目录 题目描述输入格式输出格式样例输入1样例输出1样例输入2样例输出2提交链接提示 解析参考代码 题目描述 你有一个由 n n n 个整数组成的数组 a a a 。 你要对它进行 k k k 次操作。其中一个操作是选择数组 a a a 的任意连续子数组(可能为空),并在数组的…...
Gartner 公布 2024 年八大网络安全预测
近日,Gartner 安全与风险管理峰会在悉尼举行,旨在探讨网络安全的发展前景。 本次峰会,Gartner 公布了 2024 年及以后的八大网络安全预测。 Gartner 研究总监 Deepti Gopal 表示,随着 GenAI 的不断发展,一些长期困扰网…...
《每天十分钟》-红宝书第4版-对象、类与面向对象编程(六)
盗用构造函数 上节提到原型包含引用值导致的继承问题,为了解决这种问题,一种叫作“盗用构造函数”(constructor stealing)的技术在开发社区流行起来(这种技术有时也称作“对象伪装”或“经典继承”)。基本…...
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” 无法作为数据库主体执行,因为主体 "dbo" 不存在、无法模拟这种类型的主体,或您没有所需的权限...
学点儿Java_Day12_IO流
1 IO介绍以及分类 IO: Input Output 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据…...
【python】python编程初探1----python中的基本语法,标识符,关键字,注释,多行书写,代码缩进,语句块,模块等
欢迎来CILMY23的博客喔,本篇为【python】python编程初探1----python中的基本语法,标识符,关键字,注释,多行书写,代码缩进,语句块,模块,感谢观看,支持的可以给…...
牛客周赛 Round 38
牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com) A-小红的正整数自增_牛客周赛 Round 38 (nowcoder.com) 取出最后一位判断即可 #include<iostream> #include<algorithm> #include<vector> #include<set> #include…...
漏洞扫描操作系统识别技术原理
漏洞扫描过程中,操作系统识别技术是至关重要的一步,因为它有助于扫描器针对性地选择适用的漏洞检测规则,提高扫描的准确性和效率。以下是漏洞扫描中操作系统识别技术的主要原理: **1. **TCP/IP 协议栈指纹识别** **原理**&#…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...
2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
1.题目描述 2.思路 当前的元素可以重复使用。 (1)确定回溯算法函数的参数和返回值(一般是void类型) (2)因为是用递归实现的,所以我们要确定终止条件 (3)单层搜索逻辑 二…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
「Java基本语法」变量的使用
变量定义 变量是程序中存储数据的容器,用于保存可变的数据值。在Java中,变量必须先声明后使用,声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例:声明与初始化 public class VariableDemo {publi…...
