Leetcode 螺旋矩阵

在这里插入图片描述

算法思想:

这个算法的目标是按照顺时针螺旋的顺序从矩阵中取出元素。为了做到这一点,整个思路可以分成几个关键步骤:

  1. 定义边界:首先需要定义四个边界变量:

    • left:当前左边界的索引。
    • right:当前右边界的索引。
    • top:当前上边界的索引。
    • bottom:当前下边界的索引。

    这些变量一开始会对应矩阵的外边界,然后我们会通过逐步缩小这些边界来遍历矩阵的每一层。

  2. 螺旋遍历:接下来我们会按照四个方向进行遍历:

    • 从左到右:遍历上边界的所有元素,从左到右遍历,遍历结束后将上边界向下移动一行(top++)。
    • 从上到下:遍历右边界的所有元素,从上到下遍历,遍历结束后将右边界向左移动一列(right--)。
    • 从右到左:如果还有剩余行需要遍历(即top <= bottom),遍历下边界的所有元素,从右到左遍历,遍历结束后将下边界向上移动一行(bottom--)。
    • 从下到上:如果还有剩余列需要遍历(即left <= right),遍历左边界的所有元素,从下到上遍历,遍历结束后将左边界向右移动一列(left++)。
  3. 边界条件检查:在每次从右到左或从下到上遍历之前,需要检查是否仍然有需要遍历的行或列。这是因为在某些情况下,矩阵的某些边界可能已经被其他方向的遍历覆盖了。

  4. 终止条件:当left > right或者top > bottom时,意味着已经没有元素可以遍历了,这时循环终止。

算法流程:

  • 我们从矩阵的左上角开始,按照顺时针的顺序依次遍历。
  • 每完成一圈的遍历,我们就收缩边界,继续处理内层的矩阵,直到所有元素都被处理为止。

时间复杂度分析:

  • 每次遍历矩阵中的一圈元素,而每个元素最多被访问一次,因此时间复杂度是 O(m * n),其中 m 是矩阵的行数,n 是列数。
class Solution {public List<Integer> spiralOrder(int[][] matrix) {//首先创建一个存储结果的ArrayListList<Integer> result = new ArrayList <>();//获得矩阵的行和列int rows = matrix.length;int cols = matrix[0].length;//然后定义四周墙壁int left = 0;int right = cols - 1;int top = 0;int bottom = rows - 1;//开始遍历//最后一个元素是矩阵正中心时(left = result && top = bottom),所以循环终止条件是小于等于while(left <= right && top <= bottom) { //先从左往右遍历上方的每一行, i 从 left 开始遍历到 right, 而不是从 0 开始for(int i = left; i <= right; i++) {result.add(matrix[top][i]);}//每遍历完上方的一行,需要更新 toptop++;//然后从上往下遍历最右边一列for(int i = top; i <= bottom; i++) {result.add(matrix[i][right]);}//每次遍历完最右边列,需要更新rightright--;if (top <= bottom) {//检查是否还有需要遍历的行//然后从右往左遍历最下方的行for(int i = right; i >= left; i--) {result.add(matrix[bottom][i]);}//每次遍历完最下行,需要更新bottombottom--;}if (left <= right) {//检查是否还有需要遍历的列//然后下往上遍历最左方的列for(int i = bottom; i >= top; i--) {result.add(matrix[i][left]);}//每次遍历完最左方的列,需要更新leftleft++;}}return result;}
}

为什么这一部分代码片段,需要使用2个 if 进行判断?

            if (top <= bottom) {// Traverse from right to leftfor (int i = right; i >= left; i--) {result.add(matrix[bottom][i]);}bottom--;}if (left <= right) {// Traverse from bottom to topfor (int i = bottom; i >= top; i--) {result.add(matrix[i][left]);}left++;}

在这段代码中,两个 if 判断是用来确保在进行从右到左、从下到上的遍历时,矩阵的边界没有发生交叉。如果不进行这些判断,可能会出现重复遍历或错误遍历的情况。

让我们具体分析这两个 if 判断的作用:

1. 第一个 if 判断 (if (top <= bottom))

if (top <= bottom) {// Traverse from right to leftfor (int i = right; i >= left; i--) {result.add(matrix[bottom][i]);}bottom--;
}
  • 这个 if 判断用于检查当前上边界 top 是否仍然小于等于下边界 bottom,也就是说,检查是否还有需要遍历的行。如果 top > bottom,说明矩阵的所有行已经遍历完了,再进行从右到左的操作将是没有意义的,甚至可能导致重复遍历或越界。

  • 如果 top <= bottom,则表示当前还有未处理的行,于是可以安全地从右边界 right 开始向左遍历,并在遍历结束后将下边界 bottom 向上移动,减少一行。

2. 第二个 if 判断 (if (left <= right))

if (left <= right) {// Traverse from bottom to topfor (int i = bottom; i >= top; i--) {result.add(matrix[i][left]);}left++;
}
  • 这个 if 判断用于检查当前左边界 left 是否仍然小于等于右边界 right,也就是说,检查是否还有需要遍历的列。如果 left > right,说明矩阵的所有列已经遍历完了,再进行从下到上的操作将是没有必要的,可能导致重复操作或者越界。

  • 如果 left <= right,则表示当前还有未处理的列,可以从下边界 bottom 向上遍历左边界的元素,并在遍历结束后将左边界 left 向右移动,减少一列。

为什么需要两个独立的 if 判断?

  1. 防止重复遍历:在螺旋遍历中,每次都会收缩边界(上、下、左、右)。当已经遍历完一层的矩阵后,边界会逐渐靠近矩阵的中心。如果没有这些 if 判断,在某些情况下,比如在最后一层矩阵中,可能会导致重复遍历某些行或列。例如,如果你在遍历完右到左的行后,紧接着遍历从下到上的列,而此时没有检查边界是否已经重叠,可能会再次遍历已经处理过的行或列。

  2. 防止越界:螺旋遍历会不断缩小边界,如果不做这些检查,当边界重叠或交叉时,程序可能会试图访问无效的数组索引,导致数组越界异常。通过在每次遍历前检查边界的有效性,可以确保访问的数组索引始终在合法范围内。

举例:

假设你有一个 3x3 的矩阵:

1  2  3
4  5  6
7  8  9

按顺时针遍历的顺序是:

  • 从左到右遍历第一行 [1, 2, 3]
  • 从上到下遍历第三列 [6, 9]
  • 从右到左遍历第三行 [8, 7]
  • 从下到上遍历第一列 [4]
  • 最后剩下中心元素 [5]

在这过程中,随着边界逐渐收缩,如果没有 if 判断,在遍历完成第三行时,可能会再次从右到左遍历已处理过的行,或者尝试遍历不存在的行。两个 if 判断就是为了避免这种情况发生。

总结:

  • if (top <= bottom)if (left <= right) 的作用是确保遍历时矩阵的边界没有交叉,从而避免重复访问或越界访问。
  • 它们是为了保证代码在任意大小和形状的矩阵上都能正确运行,特别是在螺旋遍历的过程中边界不断收缩的情况下。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

R语言机器学习遥感数据处理与模型空间预测技术及实际项目案例分析

随机森林作为一种集成学习方法&#xff0c;在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性&#xff0c;随机森林在降低模型方差和过拟合风险方面具有显著优势。在训练过程中&#xff0c;使用Bootstrap抽样生成不同的训练集&#xff…

夜间车辆 信号灯识别检测数据集 共3500张 YOLO数据集

夜间车辆 信号灯识别检测数据集 共3500张 YOLO数据集 夜间车辆与交通信号识别检测数据集&#xff08;Nighttime Vehicle & Traffic Signal Recognition Dataset&#xff09; 数据集概述 这是一个专为夜间环境设计的车辆和交通信号识别检测数据集&#xff0c;共包含3500张…

将python代码文件转成Cython 编译问题集

准备setup.py from distutils.core import setup from Cython.Build import cythonize import glob# 指定目标目录 python setup.py build -c mingw32 target_dir "src"# 使用glob模块匹配目录中的所有.pyx文件 pyx_files glob.glob(target_dir "/**/*.py&q…

基于STM32F103C8T6单片机的农业环境监测系统设计

本设计是基于STM32F103C8T6单片机的农业环境监测系统&#xff0c;能够完成对作物的生长环境进行信息监测和异常报警&#xff0c;并通过手机APP来实现查看信息和设定阈值的功能。为了实现设计的功能&#xff0c;该系统应该有以下模块&#xff1a;包括STM32单片机模块、水环境PH值…

STM32基础学习笔记-ADC面试基础题6

第六章、ADC 常见问题 1、基本概念&#xff1a;什么是ADC &#xff1f;作用 &#xff1f;逐次逼近型 2、传感器本质 &#xff1f;传感器、电压、ADC数值转化 &#xff1f; 3、ADC的特征 &#xff1f; 转化时间、分辨率、精度、量化误差 &#xff1f; 4、ADC框图组成部分 &…

如何安全有效地进行Temu自养号测评,提升账号权重防关联

在当今市场环境中&#xff0c;许多现成的系统或软件包往往缺乏全面的风险控制能力。掌握自养号测评技术&#xff0c;确保在运营过程中减少对外部系统的依赖。以下是搭建安全、高效运营环境的详细指导&#xff0c;特别针对手机端与电脑端环境的设置&#xff0c;以及关键资源的获…

计算机毕业设计Hadoop+Spark知识图谱体育赛事推荐系统 体育赛事热度预测系统 体育赛事数据分析 体育赛事可视化 体育赛事大数据 大数据毕设

《HadoopSpark知识图谱体育赛事推荐系统》开题报告 一、研究背景及意义 随着互联网技术的迅猛发展和大数据时代的到来&#xff0c;体育赛事数据的数量呈爆炸式增长。用户面对海量的体育赛事信息&#xff0c;常常感到信息过载&#xff0c;难以快速找到感兴趣的赛事内容。如何高…

虚拟机屏幕分辨率自适应VMWare窗口大小

文章目录 环境问题解决办法其它虚拟机和主机间复制粘贴 参考 环境 Windows 11 家庭中文版VMWare Workstation 17 ProUbuntu 24.04.1 问题 虚拟机的屏幕大小&#xff0c;是固定的。如下图&#xff0c;设置的分辨率是800*600&#xff0c;效果如下&#xff1a; 可见&#xff0c…

【PyTorch】数据读取和处理

数据读取机制DataLoader与Dataset 数据处理过程 DataLoader torch.utils.data.DataLoader 功能&#xff1a;构建可迭代的数据装载器 dataset&#xff1a;Dataset类&#xff0c;决定数据从哪里读取及如何读取batchsize&#xff1a;批大小num_works&#xff1a;是否多进程读取…

jvm专题 之 内存模型

文章目录 前言一个java对象的运行过程jvm内存分布程序的基本运行程序什么是对象&#xff1f;对象与类的关系&#xff1f;由类创建对象的顺序 前言 一个程序需要运行&#xff0c;需要在内存中开辟一块空间类是构建对象的模板&#xff0c;只有类加载到内存中才能创建对象 一个j…

Python神经求解器去耦合算法和瓦瑟斯坦距离量化评估

&#x1f3af;要点 神经求解器求解对偶方程&#xff0c;并学习两个空间之间的单调变换&#xff0c;最小化它们之间的瓦瑟斯坦距离。使用概率密度函数解析计算&#xff0c;神经求解器去耦合条件正则化流使用变量变换公式的生成模型瓦瑟斯坦距离量化评估神经求解器 &#x1f36…

SqlSugar的where条件中使用可空类型报语法错误

SQLServer数据表中有两列可空列&#xff0c;均为数值类型&#xff0c;同时在数据库中录入测试数据&#xff0c;Age和Height列均部分有值。   使用SqlSugar的DbFirst功能生成数据库表类&#xff0c;其中Age、Height属性均为可空类型。   当Where函数中的检索条件较多时&a…

针对国产化--离线安装Nginx rpm包下载 ARM64(.aarch64.rpm) 版本下载

源地址&#xff1a;https://nginx.org/packages/centos/7/aarch64/RPMS/ 可以选择系统分别进行下载对应的rmp包

Unity 设计模式 之 行为型模式 -【中介者模式】【迭代器模式】【解释器模式】

Unity 设计模式 之 行为型模式 -【中介者模式】【迭代器模式】【解释器模式】 目录 Unity 设计模式 之 行为型模式 -【中介者模式】【迭代器模式】【解释器模式】 一、简单介绍 二、中介者模式&#xff08;Mediator Pattern&#xff09; 1、什么时候使用中介者模式 2、使用…

记一次sql查询优化

记一次sql查询优化 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 今天测试环境发现一个问题&#xff0c;就是测试同事在测试的时候&#xff0c;发现cpu一直居高不下&#xff0c;然…

SDK(2 note)

复习上一次内容&#xff1a; 把前一次笔记中的代码&#xff0c;简写一下 #include <windows.h> #include<tchar.h> #include <stdio.h> #include <strsafe.h> VOID showerrormassage() {LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFF…

【春秋云境】CVE-2024-23897-Jenkins 2.441之前版本存在任意文件读取漏洞

一、靶场介绍 Jenkins 2.441及更早版本&#xff0c;以及LTS 2.426.2及更早版本没有禁用其CLI命令解析器的一个功能&#xff0c;该功能会将参数中’字符后跟的文件路径替换为该文件的内容&#xff0c;允许未经身份验证的攻击者读取Jenkins控制器文件系统上的任意文件。 二、P…

SSM+Vue共享单车管理系统

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 spring-mybatis.xml3.5 spring-mvc.xml3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作…

js中Fucntion的意义

在js中&#xff0c;我们常常如下方式写函数&#xff1a; function fn(){console.log("这是一个函数."); }; fn(); 在js中&#xff0c;函数本质就是一个对象。 那么&#xff0c;结合我的上一篇文章&#xff1a;通俗讲解javascript的实例对象、原型对象和构造函数以及…

谷歌浏览器如何更改下载文件存放的方式及其路径?

1、点击谷歌浏览器右上角的【三个点】 2、选择【设置】&#xff0c;再选择【下载内容】 3、打开【下载完成后显示下载内容】开关&#xff0c; 则&#xff1a;下载网页上的东西之后&#xff0c;会显示在【谷歌浏览器】的右侧&#xff0c;并显示具体下载文件在右侧&#xff1a;…