力扣第五十四题——螺旋矩阵
内容介绍
给你一个
m行n列的矩阵matrix,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] 输出:[1,2,3,4,8,12,11,10,9,5,6,7]提示:
m == matrix.lengthn == matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100
完整代码
int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};int* spiralOrder(int** matrix, int matrixSize, int* matrixColSize, int* returnSize) {if (matrixSize == 0 || matrixColSize[0] == 0) {*returnSize = 0;return NULL;}int rows = matrixSize, columns = matrixColSize[0];int visited[rows][columns];memset(visited, 0, sizeof(visited));int total = rows * columns;int* order = malloc(sizeof(int) * total);*returnSize = total;int row = 0, column = 0;int directionIndex = 0;for (int i = 0; i < total; i++) {order[i] = matrix[row][column];visited[row][column] = true;int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];if (nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn]) {directionIndex = (directionIndex + 1) % 4;}row += directions[directionIndex][0];column += directions[directionIndex][1];}return order;
}
思路详解
一、问题背景
给定一个二维数组,要求按照螺旋顺序遍历数组,并返回一个一维数组,其中包含按螺旋顺序遍历得到的元素。
二、解题思路
-
边界处理:
- 首先检查数组是否为空,如果为空,则直接返回空数组。
-
初始化:
- 创建一个二维数组
visited,用于标记数组中已经遍历过的元素。 - 初始化数组的大小为行数乘以列数。
- 创建一个一维数组
order,用于存储按螺旋顺序遍历得到的元素。
- 创建一个二维数组
-
遍历策略:
- 定义一个方向数组
directions,包含四个方向:上、右、下、左。 - 初始化起点
row和column,以及方向索引directionIndex。 - 遍历数组,按照螺旋顺序填充
order数组。 - 在遍历过程中,如果下一个位置越界或者已经遍历过,则改变方向。
- 定义一个方向数组
-
结果返回:
- 遍历完成后,返回
order数组。
- 遍历完成后,返回
三、代码详解
- 边界处理:
- 如果数组为空,直接返回空数组。
if (matrixSize == 0 || matrixColSize[0] == 0) {*returnSize = 0;return NULL;
}
- 初始化:
- 创建
visited数组并初始化为0。 - 创建
order数组并分配内存。 - 初始化
rows、columns、total和directionIndex。
- 创建
int rows = matrixSize, columns = matrixColSize[0];
int visited[rows][columns];
memset(visited, 0, sizeof(visited));
int total = rows * columns;
int* order = malloc(sizeof(int) * total);
*returnSize = total;
- 遍历策略:
- 初始化起点
row和column,以及方向索引directionIndex。 - 遍历数组,按照螺旋顺序填充
order数组。 - 在遍历过程中,如果下一个位置越界或者已经遍历过,则改变方向。
- 初始化起点
int row = 0, column = 0;
int directionIndex = 0;
for (int i = 0; i < total; i++) {order[i] = matrix[row][column];visited[row][column] = true;int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];if (nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn]) {directionIndex = (directionIndex + 1) % 4;}row += directions[directionIndex][0];column += directions[directionIndex][1];
}
- 结果返回:
- 遍历完成后,返回
order数组。
- 遍历完成后,返回
return order;
四、总结
通过上述步骤,我们能够有效地遍历二维数组并按照螺旋顺序返回一维数组。关键在于正确地初始化数组、遍历策略和结果返回。这种方法的时间复杂度为O(n),其中n为数组的大小。空间复杂度为O(n),用于存储一维数组和二维数组。
知识点精炼
一、核心概念
- 边界条件检查:在开始遍历之前,检查输入的二维数组是否为空。
- 二维数组访问:使用两个索引变量来访问二维数组中的元素。
- 动态数组分配:在内存中动态分配一维数组来存储遍历结果。
- 方向数组:使用一个二维数组来表示遍历的方向。
二、知识点精炼
-
初始化:
- 创建一个二维数组
visited来标记数组中已经遍历过的元素。 - 创建一个一维数组
order来存储按螺旋顺序遍历得到的元素。
- 创建一个二维数组
-
遍历策略:
- 初始化起点
row和column,以及方向索引directionIndex。 - 遍历数组,按照螺旋顺序填充
order数组。 - 在遍历过程中,如果下一个位置越界或者已经遍历过,则改变方向。
- 初始化起点
-
结果返回:
- 遍历完成后,返回
order数组。
- 遍历完成后,返回
三、性能分析
- 时间复杂度:O(n),其中n为数组的大小。
- 空间复杂度:O(n),用于存储一维数组和二维数组。
四、实际应用
- 数据处理:在处理二维数据时,这种算法可以帮助我们按照特定顺序访问数据。
- 算法竞赛:在算法竞赛中,掌握这种算法对于解决与二维数组遍历相关的问题非常有帮助。
五、代码实现要点
- 边界条件检查:确保输入的二维数组不为空。
- 动态数组分配:正确分配内存空间,避免内存泄漏。
- 遍历策略:正确实现螺旋遍历策略,避免数组越界和重复访问。
- 结果返回:正确返回遍历结果。
减少空间复杂度的思路
在原始代码中,我们使用了一个二维数组visited来标记已经遍历过的元素,这导致了较高的空间复杂度。为了减少空间复杂度,我们可以使用一个一维数组来替代二维数组,这样可以将空间复杂度从O(n)降低到O(1)。
以下是优化后的代码:
int* spiralOrder(int** matrix, int matrixSize, int* matrixColSize, int* returnSize) {if (matrixSize == 0 || matrixColSize[0] == 0) {*returnSize = 0;return NULL;}int rows = matrixSize, columns = matrixColSize[0];int* order = malloc(sizeof(int) * (rows * columns));*returnSize = rows * columns;int top = 0, bottom = rows - 1, left = 0, right = columns - 1;int index = 0;while (top <= bottom && left <= right) {// Traverse the top rowfor (int i = left; i <= right; i++) {order[index++] = matrix[top][i];}top++;// Traverse the rightmost columnfor (int i = top; i <= bottom; i++) {order[index++] = matrix[i][right];}right--;// If there is still a row leftif (top <= bottom) {// Traverse the bottom rowfor (int i = right; i >= left; i--) {order[index++] = matrix[bottom][i];}bottom--;}// If there is still a column leftif (left <= right) {// Traverse the leftmost columnfor (int i = bottom; i >= top; i--) {order[index++] = matrix[i][left];}left++;}}return order;
}
在这个优化版本中,我们使用了一个一维数组order来存储遍历结果,而不是使用一个二维数组visited来标记已经遍历过的元素。我们通过维护四个边界变量(top、bottom、left、right)来控制遍历的方向,并在每次迭代中只遍历尚未访问的部分。这种方法避免了使用额外的空间来存储已访问的元素,从而将空间复杂度降低到O(1)。
相关文章:
力扣第五十四题——螺旋矩阵
内容介绍 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]示例 2: 输入:matrix …...
中创算力:以知识产权转化运用促进高质量发展
创新是引领发展的第一动力,保护知识产权就是保护创新。为深入实施知识产权公共服务普惠工程,促进知识产权公共服务更好服务高水平科技,国家知识产权局发布关于全面提升知识产权公共服务效能的指导意见。 在政策落地过程中,如何精…...
C语言9~10 DAY(合集)
数组的概念 什么是数组 数组是相同类型,有序数据的集合。 数组的特征 数组中的数据被称为数组的元素,是同构的 数组中的元素存放在内存空间里 (char player_name[6]:申请在内存中开辟6块连续的基于char类型的变量空间) 衍生概念&#x…...
【Kubernetes】应用的部署(一):金丝雀部署
应用的部署(一):金丝雀部署 在项目迭代开发过程中,经常需要对应用进行上线部署。上线部署策略主要有 3 种:金丝雀部署、蓝绿部署 和 滚动部署。 金丝雀部署 也被叫作 灰度部署。金丝雀部署过程:先让一部分…...
1.面试准备篇
筛选简历 找实习用处不大 简历注意事项 注意职业技能和项目经历 职业技能 黄金位置 针对性 引导面试官提问 只写会的 不会的不能写 项目描述 主要设计… 展示指标 找练手项目 来源:Gitee 或者github 主要关注点:功能实现、常见问题、系统设计 面试过程 一面…...
Spring: try-catch 是否还会回滚
问题出现: try-catch 语句 依旧会抛出如下错误 org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnlyat org.springf…...
spdlog日志库--基础介绍
文章目录 1. 简介1.1. spdlog代码特点1.2. 说明1.3. spdlog架构 2. spdlog的安装2.1. 使用包管理器安装2.2. 使用源码安装2.3. 仅使用头文件 3. 相关概念3.0 常用的头文件3.1. level_enum3.2. sink3.3. logger3.4 格式输出3.5 对齐方式3.6 截断3.7 字符串格式化fmt 4. 特性4.1.…...
【网络】网络编程套接字(二)
网络编程套接字(二) 文章目录 1.单执行流的TCP网络程序1.1服务端创建套接字1.2服务端绑定1.3服务端监听1.4服务端获取链接1.5服务端处理请求1.6客户端创建套接字1.7客户端连接服务器1.8客户端发起请求 2.多进程版的TCP网络程序2.1单执行流的弊端2.2多进…...
1.1、centos stream 9安装Kubernetes v1.30集群 环境说明
最近正在学习kubernetes,买了一套《Kubernetes权威指南 从Docker到Kubernetes实践全接触(第六版)》这本书讲得很好,上下两册,书中k8s的版本是V1.29,目前官网最新版本是v1.30。强烈建议大家买一套看看。 Kubernetes官网地址&#x…...
Redis3
目录 什么是缓存穿透?怎么解决? 什么是缓存雪崩?怎么解决? 如何保证数据库和缓存的数据一致性? 如何保证Redis服务高可用? 哨兵的作用 Redis虚拟槽分区有什么优点? 为什么Redis集群最大槽…...
Oracle数据巡检 - 设计巡检模板
设计巡检模板 明确巡检数据库等信息 包括数据库种类、版本、架构、数量等,例如 Oracle DG和Oracle RAC数据库巡检项肯定会有差异,Oracle 11g和12c版本巡检内容也会有所不同。 明确巡检项 这一块需要结合自身的运维经验,列出详尽的巡检项&…...
优盘未格式化数据恢复实战指南
在数字时代,优盘(USB闪存驱动器)作为便携存储媒介,承载着无数重要的文件与数据。然而,当您插入优盘准备访问资料时,却遭遇了“驱动器未被格式化”的提示,这无疑是一场突如其来的数据危机。本文将…...
【python基础】python基础习题练习(一)
文章目录 一. python语言简介二. python基本语法与常用函数三. python基本数据类型一.选择题二.编程题四. python组合数据类型一.选择题二.简答题三.编程题一. python语言简介 查看python是否安装成功的命令是:python -vPython IDE有:pyCharm、Spyder、Jupter NotebookPython…...
GESP 4级样题 ---> 绝对素数
这题需要判断一个数和它的反转后的数是否都为素数。 可以转成 string 后 reverse 一下。 AC CODE: #include <bits/stdc.h> using namespace std; typedef long long LL; bool isPrime(int x){if(x<2) return false;for(int i2;i*i<x;i){if(x%i0) re…...
大语言模型系列 - Transformer
1. 简介 1.1. 概述 大语言模型Transformer是一种由谷歌公司提出的基于注意力机制的神经网络模型,它在自然语言处理(NLP)领域取得了显著成就,并逐渐被应用于其他领域如语音识别、计算机视觉和强化学习等。 1.2. 学习资源 以下是一些学习大语言模型Transformer的资源地址…...
Java面试之操作系统
1、冯诺依曼模型 运算器、控制器、存储器、输入设备、输出设备 32位和64位CPU最主要区别是一次性能计算多少字节数据,如果计算的数额不超过 32 位数字的情况下,32 位和 64 位 CPU 之间没什么区别的,只有当计算超过 32 位数字的情况下&#…...
springboot船舶维保管理系统--论文源码调试讲解
第二章 相关技术 本次开发船舶维保管理系统使用的是Vue进行程序开发,船舶维保管理系统的数据信息选择MySQL数据库进行存放。 2.1 VUE介绍 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue…...
【机器学习西瓜书学习笔记——神经网络】
机器学习西瓜书学习笔记【第五章】 第五章 神经网络5.1神经元模型5.2 感知机与多层网络学习感知机学习率成本/损失函数梯度下降 5.3 BP神经网络(误差逆传播)5.4 全局最小与局部极小5.5 其他常见神经网络RBF网络RBF 与 BP 最重要的区别 ART网络 第五章 神…...
安装 electron 报错解决
1. 报错 大概率由镜像问题导致 2. 解决 2.1 打开 npm 配置 npm config edit 2.2 添加配置 registryhttps://registry.npmmirror.comelectron_mirrorhttps://cdn.npmmirror.com/binaries/electron/electron_builder_binaries_mirrorhttps://npmmirror.com/mirrors/electron…...
【Material-UI】Icon Button 组件详解
文章目录 一、基础用法1. 禁用状态 二、大小(Sizes)1. 小尺寸(Small)2. 大尺寸(Large) 三、颜色(Colors)1. 主题颜色2. 自定义颜色 四、高级用法和最佳实践1. 无障碍性(A…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

