【leetcode常见面试题】螺旋矩阵解题思路

2023-05-16

文章目录

  • 螺旋矩阵
    • 解题思路
      • 先找行进路线
      • 找每条路线的结束位置
      • 再找每条路线的结束位置
      • 模拟行走
  • 螺旋矩阵 II
  • 总结

螺旋矩阵

在这里插入图片描述

解题思路

本题可以采用模拟的方式,设4种行走方向,如下图:

先找行进路线

4个方向的行走路线分别是:从左到右,从上到下,从右到左,从下到上。

并且
从左到右是从第一行开始,
从上到下是从最后一列开始,
从右到左是从最后一行开始,
从下到上是从第一列开始。

在这里插入图片描述

代码定义如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    return ans;
}

当第一圈走完以后,4个方向一定都会向内收缩一圈。

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 第一行走完
    leftToRight++;
    // 最后一列走完
    upToDown--;
    // 最后一行走完
    rightToLeft--;
    // 第一列走完
    downToUp++;
    return ans;
}

找每条路线的结束位置

现在我们只需要搞清楚如何定义每个方向算走完这个逻辑即可,从图上可以看出,每个方向的结束位置,就是下一个方向的开始位置,比如从左向右走时,行保持不变,列应该一直走到下一个方向的开始位置,即upToDown定义的范围。
从上到下走时,列保持不变,行应该一直走到下一个方向的开始位置,即rightToLeft定义的范围。

由此可得,如下代码:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    
    // 1. 从左到右
    for(int i = ?; i <= upToDown; i++){
    }
    // 从左到右走完
    leftToRight++;
    
    // 2. 从上到下
    for(int i = ?; i <= rightToLeft; i++){
    }
    // 从上到下走完
    upToDown--;
    
    // 3. 从右到左
    for(int i = ?; i >= downToUp; i--){
    }
    // 从右到左走完
    rightToLeft--;
    
    // 4. 从下到上
    for(int i = ?; i >= leftToRight; i--){
    }
    // 从下到上走完
    downToUp++;
    return ans;
}

再找每条路线的结束位置

弄清楚4个方向的结束位置之后,剩下来的只要在定义好开始位置就好了,很明显,上一个方向的结束位置,即是当前方向的开始位置。

所以,我们填入4个方向的开始值后,代码如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 1. 从左到右
    for (int i = downToUp; i <= upToDown; i++) {
    }
    // 从左到右走完
    leftToRight++;
    // 2. 从上到下
    for (int i = leftToRight; i <= rightToLeft; i++) {
    }
    // 从上到下走完
    upToDown--;
    // 3. 从右到左
    for (int i = upToDown; i >= downToUp; i--) {
    }
    // 从右到左走完
    rightToLeft--;
    // 4. 从下到上
    for (int i = rightToLeft; i >= leftToRight; i--) {
    }
    // 从下到上走完
    downToUp++;
    return ans;
}

模拟行走

接下来,让每个方向走起来,并挨个添加到集合中,代码如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 1. 从左到右
    for (int i = downToUp; i <= upToDown; i++) {
        ans.add(matrix[leftToRight][i]);
    }
    // 从左到右走完
    leftToRight++;
    // 2. 从上到下
    for (int i = leftToRight; i <= rightToLeft; i++) {
        ans.add(matrix[i][upToDown]);
    }
    // 从上到下走完
    upToDown--;
    // 3. 从右到左
    for (int i = upToDown; i >= downToUp; i--) {
        ans.add(matrix[rightToLeft][i]);
    }
    // 从右到左走完
    rightToLeft--;
    // 4. 从下到上
    for (int i = rightToLeft; i >= leftToRight; i--) {
        ans.add(matrix[i][downToUp]);
    }
    // 从下到上走完
    downToUp++;
    return ans;
}

矩阵大小即是一共要走的步数,那么每走一步记录一下,直到走满矩阵大小即表示走完。

最后代码实现如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    int step = 0;
    int totalStep = matrix.length * matrix[0].length;
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 外层while控制每一圈走完后,要不要继续走
    // 里面的每一个for控制每一步走完后,要不要继续走
    while (step < totalStep) {
        // 1. 从左到右
        for (int i = downToUp; i <= upToDown && step < totalStep; i++) {
            ans.add(matrix[leftToRight][i]);
            step++;
        }
        // 从左到右走完
        leftToRight++;
        // 2. 从上到下
        for (int i = leftToRight; i <= rightToLeft && step < totalStep; i++) {
            ans.add(matrix[i][upToDown]);
            step++;
        }
        // 从上到下走完
        upToDown--;
        // 3. 从右到左
        for (int i = upToDown; i >= downToUp && step < totalStep; i--) {
            ans.add(matrix[rightToLeft][i]);
            step++;
        }
        // 从右到左走完
        rightToLeft--;
        // 4. 从下到上
        for (int i = rightToLeft; i >= leftToRight && step < totalStep; i--) {
            ans.add(matrix[i][downToUp]);
            step++;
        }
        // 从下到上走完
        downToUp++;
    }
    return ans;
}

螺旋矩阵 II

使用同样的套路即可快速完成
在这里插入图片描述

public int[][] generateMatrix(int n) {
    int[][] ans = new int[n][n];
    int step = 0;
    int leftToRight = 0;
    int upToDown = n - 1;
    int rightToLeft = n - 1;
    int downToUp = 0;
    while (step < n * n) {
        for (int i = downToUp; i <= upToDown && step < n * n; i++) {
            ans[leftToRight][i] = ++step;
        }
        leftToRight++;
        for (int i = leftToRight; i <= rightToLeft && step < n * n; i++) {
            ans[i][upToDown] = ++step;
        }
        upToDown--;
        for (int i = upToDown; i >= downToUp && step < n * n; i--) {
            ans[rightToLeft][i] = ++step;
        }
        rightToLeft--;
        for (int i = rightToLeft; i >= leftToRight && step < n * n; i--) {
            ans[i][downToUp] = ++step;
        }
        downToUp++;
    }
    return ans;
}

总结

记住三个关键点即可:

  1. 总共上下左右4个方向。
  2. 每个方向的开始都由上一个方向的结束来决定。
  3. 每个方向的结束都由下一个方向的开始来决定。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【leetcode常见面试题】螺旋矩阵解题思路 的相关文章

  • C++对象的销毁

    对象的销毁 一般来说 xff0c 需要销毁的对象都应该做清理 解决方案 1 为每个类都提供一个public的free函数 xff1b 2 对象不再需要时立即调用free函数进行清理 析构函数 1 C 43 43 的类中可以定义一个特殊的清理
  • C++中类中的函数重载

    类中的函数重载 函数重载的回顾 1 函数重载的本质就是为相互独立的不同函数 xff1b 2 C 43 43 中通过函数名和函数参数确定函数调用 xff1b 3 无法直接通过函数名得到重载函数的入口地址 xff1b 4 函数重载必然发生在同一
  • C++中的字符串类

    字符串类 历史遗留的问题 1 C语言不支持真正意义上的字符串 xff1b 2 C语言用字符数组和一组实现字符串操作 xff1b 3 C语言不支持自定义类型 xff0c 因此无法获得字符类型 xff1b 解决方案 1 从C到C 43 43 的
  • MySQL中的Block Nested Loop优化分析

    前言 一般在MySQL规范中 xff0c 都会规定如果两张表进行join查询 xff0c 那么join的字段一定要有索引 xff0c 在之前的文章中我们分析了MySQL join大小表前后顺序影响分析 xff0c 这是在有索引的情况下 xf
  • C++之类模板的概念和意义

    类模板 一些类主要用于存储和组织数据元素 类中数据组织的方式和数据元素的具体类型无关 如 xff1a 数组类 链表类 Stack Queue类 等 1 C 43 43 中将模板的思想应用于类 xff0c 使得类的实现不关注数据元素的具体类型
  • C++之单例类模板

    需求的提出 在架构设计时 xff0c 某些类在整个系统生命周期中最多只能有一个对象存在 xff08 Single Instance xff09 要控制类的对象数目 xff0c 必须对外隐藏构造函数 xff1b 思路 xff1a 1 将构造函
  • 【无标题】

    绘图控件GraphicsView 一 GraphicsView简介 1 QT有多种绘图相关的技术 xff0c 我们将在第2部分 2 4 QT绘图和图表 中比较详细系统的讲 2 本节简单讲一下GraphicsView的基本理论 xff0c 并
  • uboot源码分析之start.S解析

    1 start S引入 1 1 u boot lds中找到start S入口 1 在uboot中因为有汇编阶段参与 xff0c 因此不能直接找main c 整个程序的入口取决于链接脚本中ENTRY声明的地方 ENTRY start 因此 s
  • uboot启动第二阶段

    uboot启动第二阶段 start armboot函数简介 一个很长的函数 1 这个函数在uboot lib arm board c的第444行开始到908行结束 2 450行还不是全部 xff0c 因为里面还调用了别的函数 3 为什么这么
  • cmake设置编译类型为release命令

    cmake编译类型通常默认为debug xff0c 但是在编译软件时 xff0c 一般都需要使用release版本的 xff0c debug太慢了 设置为release版本可以在cmake文件里进行 xff0c 也可以在运行cmake命令时
  • 设计模式之单例模式(Singleton),以C++为例,实现日志输出。

    Hello大家好 xff0c 好久没更新了 xff0c 今天给大家补上最基础的设计模式 xff1a 单例模式 这个单例模式实在是我的心结啊 xff0c 2021年末左右面试京东算法岗 xff0c 面试官让我写一个单例 xff0c 没写出来
  • 源码分析MyBatis对数值(int、double)类型进行test判断的误区

    文章目录 问题描述问题分析验证解析表达式执行解析后表达式分别测试两个条件 查询Ognl官方文档验证问题解决 问题描述 在如下判断中 xff0c 如果type类型为int xff0c 那么对于type 61 39 39 部分判断会出现一些问题
  • Git报错:error: xxxx bytes of body are still expected.

    git一个很老的项目 xff0c 项目深度很深 xff0c 报错 xff1a error 7857 bytes of body are still expected fetch pack unexpected disconnect whil
  • 设计模式之代理模式(Proxy),以C++为例,实现远程代理、虚拟代理、保护代理等。

    兄弟姐妹们好 xff0c 又是好久没有更新了 xff0c 今天给大家简单介绍代理模式 xff0c 一个很简单的设计模式 xff0c 旨在不改变原对象的情况下通过代理对象来控制对原对象的访问 代理模式根据具体情况还可以分为远程代理 虚拟代理
  • C++ 互斥锁原理以及实际使用介绍

    兄弟姐妹们 xff0c 我又回来了 xff0c 今天带来实际开发中都需要使用的互斥锁的内容 xff0c 主要聊一聊如何使用互斥锁以及都有哪几种方式实现互斥锁 实现互斥 xff0c 可以有以下几种方式 xff1a 互斥量 xff08 Mute
  • 【C++】使用【windwos api】获取windwos计算机的基本信息

    今天来一篇获取windows计算机的基本信息的文章 xff0c 包含计算机名称 操作系统版本 处理器信息 内存信息 硬盘信息 显示器信息 网络信息 驱动程序信息 电源信息 其他硬件信息 目录 一 windwos系统包含的基本信息 二 获取信
  • C++ POCO库的基础介绍(Windwos和Linux)

    简单介绍C 43 43 POCO库能干什么 xff0c 后续有时间的话将根据其每个点详细解析 xff0c 关注我 本篇包含POCO库简单介绍 下载以及安装方式 简单代码示例 目录 一 POCO简单介绍 1 1 POCO库的基本模块 1 2
  • ROS踩坑记录

    ROS踩坑记录 问题 xff1a ubuntu 没有 dev ttyUSB0问题 xff1a 运行 launch 文件或 ROS 节点时出现 exit code 9 错误提示问题 xff1a windows使用vscode远程连接 xff0
  • STM32串口数据接收 --环形缓冲区

    STM32串口数据接收 环形缓冲区 环形缓冲区简介 在单片机中串口通信是我们使用最频繁的 xff0c 使用串口通信就会用到串口的数据接收与发送 xff0c 环形缓冲区方式接收数据可以更好的保证数据丢帧率第 在通信程序中 xff0c 经常使用
  • 如何设计安全可靠的开放接口---对请求参加密保护

    文章目录 如何设计安全可靠的开放接口 系列前言AES加解密代码实现 如何设计安全可靠的开放接口 系列 1 如何设计安全可靠的开放接口 之Token 2 如何设计安全可靠的开放接口 之AppId AppSecret 3 如何设计安全可靠的开放

随机推荐

  • rosdep init报错解决方法

    rosdep init报错解决方法 很多小伙伴在安装ROS的过程中都不可避免的要执行rosdep init和rosdep update这两行命令行 xff0c 这也是在安装ROS的过程中最让人头疼的两步 xff0c 一般都没法一次成功 xf
  • NVIDIA Jetson Nano/Xavier NX 扩容教程

    在售的 NVIDIA Jetson 内置 16 GB 的 eMMC xff0c 并已安装了 ubuntu 18 04 LTS 和 NVIDIA JetPack 4 6 xff0c 所以剩余的用户可用空间大约 2GB xff0c 这对将 NV
  • 深度学习框架YOLOv3的C++调用

    深度学习框架YOLOv3的C 43 43 调用 深度学习框架YOLOv3的C 43 43 调用 xff08 1 xff09 tensorflow版本的YOLOv3的C 43 43 调用 xff08 失败 xff09 xff08 2 xff0
  • 基于GPT-2实现图像文本生成

    原理 使用GPT 2模型处理文本 xff0c 做decoder 使用google的vit base patch16 224模型处理图像 xff0c 做encoder 最后通过VisionEncoderDecoderModel将这两个模型粘起
  • C语言中常见的两个比较字符串是否相等的函数strcmp和strncmp

    函数 xff1a strcmp和strncmp strcmp 使用格式 xff1a include lt string h gt int strcmp const char s1 const char s2 设这两个字符串为str1 xff
  • sprintf和printf 用法的区别

    printf 的作用是标准化输出 xff0c 默认的对象是标准输出缓冲区 xff0c 要有一定的条件才能把缓冲区里面的数据输出 sprintf 作用是格式化输出函数 xff0c 保存字符串到缓冲区中 xff0c 起到拼接字符串的作用 功能
  • 第六篇,STM32脉冲宽度调制(PWM)编程

    1 PWM概念 PWM叫脉冲宽度调制 Pulse Width Modulation xff0c 通过编程控制输出方波的频率和占空比 高低电平的比例 xff0c 广泛应用在测量 xff0c 通信 xff0c 功率控制等领域 呼吸灯 xff0c
  • 第十篇,STM32串口蓝牙编程

    1 串口蓝牙概念 串口蓝牙是一个蓝牙模块 xff0c 内部有蓝牙模块和程序 xff0c 可以进行蓝牙通信 xff0c 同时提供一个串口接口 xff0c 通过串口可以配置蓝牙模块进行数据传输 2 使用串口3连接蓝牙模块 3 手机上安装蓝牙调试
  • LeetCode岛屿问题通用解决模板

    文章目录 前言第一题 xff1a 求岛屿的周长模板整理遍历方向确定边界重复遍历问题处理 模板解第一题第二题 xff1a 求岛屿数量第三题 xff1a 岛屿的最大面积第四题 xff1a 统计子岛屿第五题 xff1a 统计封闭岛屿的数目第六题
  • 第十四篇,STM32的CAN总线通信

    1 CAN总线的概念 CAN指的是控制器局域网网络 Controller Area Network xff0c 由德国博世汽车电子厂商开发出来 CAN使用差分信号 xff0c 具有较强的抗干扰能力和传输稳定性 CAN属于多主通信 xff0c
  • OpenCV图像处理学习十九,像素重映射cv::remap

    一 像素重映射概念 重映射就是把输入图像中各个像素按照制定的规则顺序映射到另外一张图像的对应位置上去 xff0c 形成一张新的图像 二 像素映射API函数接口 cv remap xff08 InputArray src 输入图像 Outpu
  • OpenCV图像处理学习二十一,直方图比较方法

    一 直方图比较 直方图比较是对输入的两张图像进行计算得到直方图H1与H2 xff0c 归一化到相同的尺度空间 xff0c 然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度 xff08 每张图像都有唯一的直方图与之对应 xff0
  • 嵌入式FreeRTOS学习九,任务链表的构成,TICK时间中断和任务状态切换调度

    一 tskTaskControlBlock 函数结构体 在tskTaskControlBlock 任务控制块结构体中 xff0c 其中有任务状态链表和事件链表两个链表成员 xff0c 首先介绍任务状态链表这个结构 xff0c 这个链表通常用
  • SOAP传输协议

    一 HTTP传输协议 超文本传输协议 xff08 HyperText Transfer Protocol xff0c 缩写 xff1a HTTP xff09 xff0c 它是基于请求 响应的模式协议 xff0c 客户端发出请求 xff0c
  • ONVIF简介

    一 什么是ONVIF ONVIF规范描述了网络视频的模型 接口 数据类型以及数据交互的模式 并复用了一些现有的标准 xff0c 如WS系列标准等 ONVIF规范的目标是实现一个网络视频框架协议 xff0c 使不同厂商所生产的网络视频产品 x
  • gsoap工具生成onvif设备搜索(remotediscovery)代码框架

    什么是gsoap工具 xff1f gSOAP 提供了两个工具来方便开发人员使用 C C 43 43 语言快速开发Web 服务应用 xff0c 通过 gSOAP 提供的这两个工具 xff0c 开发人员可以快速生成服务端与客户端代码框架 xff
  • Latex之给字符上加横线、波浪等

    Latex 前几天想在 x x x 上加波浪号 xff0c 一时间忘记怎么打 xff0c 现在记录下来 xff0c 以后好查阅 加 号 xff1a hat x 加横线 xff1a overline x 加宽 xff1a widehat x
  • 数据结构笔记-2(线性表)

    线性表 2 1 线性表 1 定义 是零个或多个具有相同类型的数据元素的有序数列 xff1b xff08 长度等于零的线性表为空表 xff09 非空线性表通常记为 xff1a L xff1d a 1 xff0c a 2 xff0c xff0c
  • 数据结构-6(图)

    图 图的逻辑结构 图的定义 xff1a 图是由顶点的有穷非空集合和顶点之间边的集合组成 xff0c 通常表示为 xff1a G 61 V xff0c E 其中 xff1a G表示一个图 xff0c V是图G中顶点的集合 xff0c E是图G
  • 【leetcode常见面试题】螺旋矩阵解题思路

    文章目录 螺旋矩阵解题思路先找行进路线找每条路线的结束位置再找每条路线的结束位置模拟行走 螺旋矩阵 II总结 螺旋矩阵 解题思路 本题可以采用模拟的方式 xff0c 设4种行走方向 xff0c 如下图 xff1a 先找行进路线 4个方向的行