​LeetCode刷题实战54:螺旋矩阵

Python输出螺旋形数组 Python输出螺旋形数组思路 思路 1、先初始化一个二维数组,从外向内,一圈圈填充。 2、每一圈由每组3个,共4组数构成。确定起点、数量、和方向即可用4个循环完成填充。 3、简化思路:循环第1组(蓝色),相应可以由步长3确定后面3组的位置,即循环1次即可。 按上图标数顺序依次填充即可完成一圈。 代码如下: #!/usr/bin/python3 # -*- coding: utf-8 _*_ ... 阅读详情

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 螺旋矩阵,我们先来看题面:

https://leetcode-cn.com/problems/spiral-matrix/

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

题意

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

样例

示例 1:

输入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

示例 2:

输入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

解题

https://www.cnblogs.com/techflow/p/12790451.html

通过螺旋丸我们都知道螺旋形是什么意思,所以所谓的螺旋矩阵,就是按照螺旋形的顺序来遍历一个数组,或者说矩阵。我们可以看下下图:

箭头标注的顺序就是螺旋的顺序,这道题让我们求的就是按照螺旋的顺序遍历之后的结果。

背景

这道题的题意非常简单,我想大家肯定都能看明白,但是真的要上手去做会发现还是蛮困难的。主要的难点就是我们遍历的顺序一直在变化,并且变化的速度也是在变化的。虽然从某种程度上来说,这些变化都是有迹可循的,但是即便如此,把这些规律抽象出来写成简单易懂没有bug的代码也并不是一件容易的事情。

如果我没有记错的话,当年我大二的时候学校里的acm校赛有一题就是这个,一模一样的原题。虽然非常简单,每个人都知道怎么做,但是最后的通过率并不高。

这并不完全是出题人的恶意,其实这类问题在acm的比赛当中还是很常见的。经常会有一些题目很清晰明确,你只需要照着实现就可以了的题目。考察的就是选手的抽象和编码能力,虽然题意不难,但是在比赛高压的场景下想要快速写出一个几百行包含一系列复杂逻辑的程序并且没有bug,还是非常困难的一件事。由于这类题目的关键就是让我们模拟出来题目的意思,所以也被称为模拟题。

想要比较顺手地写出这道题,需要一个很常用的技巧或者说惯例,这也是这篇文章的关键。

方向数组

在许多问题当中我们经常会遇到这样一个问题,比如我们需要遍历一个迷宫,需要沿着现实世界当中上下左右或者是东南西北的方向进行移动。在移动的过程当中自然就涉及各种各样的方向,于是我们需要用代码来表示方向。

比如我们画一个小人,它所在的坐标是(x, y),它有东南西北四个方向可以选。我们假设他每次移动一个单位的距离,我们很容易就得出它往各个方向移动之后的新坐标。

根据数学上向量的定义,我们可以写出这四个方向的方向单位向量:[0, 1], [0, -1], [1, 0], [-1, 0]。

我们把这些向量存放进一个常量数组当中,就得到了方向数组。当我们需要遍历所有方向的时候,我们只需要遍历这个数组即可。

不仅如此,如果我们对方向的遍历顺序有要求,它也完全可以实现。比如在这题当中,我们可以发现,螺旋遍历每一次改变顺序其实都是向左转了90度。

原本朝东的旋转之后变成了朝南,朝南的变成了朝西,朝西的成了朝北,而朝北的成了朝东。那么我们只需要把方向按照东南西北的顺序摆放,我们每次把方向数组的下标增加一位并对4取模,就得到了下一个方向。

这个技巧并不难理解,但是可以大大简化我们的代码。

解答

理解了方向数组之后剩下的就容易多了,我们观察一下上面螺旋遍历的过程,每一次改变方向遍历的长度虽然不同,但是每一次改变的原因是一致的,就是这个方向上已经遍历到头了,所以我们需要变更方向。明白了这点其实就很容易了,我们只需要维护每个方向上的终点,每次到终点则进行变向。由于矩阵当中元素的数量是固定的,我们遍历的次数也就知道了,所以只要把变更方向的事情处理好,这道题也就解决了。

我们来看下代码:

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        # 定义方向数组
        fx = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        n = len(matrix)
        if n == 0:
            return []
        m = len(matrix[0])
        
        ret = []
        # 定义边界数组
        # 边界数组和旋转的顺序也是对应的
        # 第一次旋转之后上边界+1,所以第0位是上边界
        # 第二次旋转之后,右边界-1
        # 以此类推
        condition = [0, m-1, n-1, 0]
        x, y, dt = 0, 0, 0
        for i in range(n * m):
            ret.append(matrix[x][y])
            x_, y_ = x + fx[dt][0], y + fx[dt][1]
            # 如果已经越过边界了,则需要转向
            if x_ < condition[0] or x_ > condition[2] or y_ < condition[3] or y_ > condition[1]:
                # 更新边界
                if dt in (1, 2):
                    condition[dt] -= 1
                else:
                    condition[dt] += 1
                    
                # 转向,并且重新移动
                dt = (dt + 1) % 4
                x_, y_ = x+fx[dt][0], y+fx[dt][1]
                # print(x_, y_)
            x, y = x_, y_
            
        return ret

我们观察一下代码,还有一个我们刚才没有提到的细节。我们在移动的时候,并不是直接在原变量上进行变更,因为如果一旦移动超界或者触发其他非法的情况,那么我们就无法回滚了。所以我们会创建新的x和y的变量来表示移动之后的位置,即使移动到了非法位置,也不会影响之前的结果。这也是一个常用的技巧,在Python当中,我们在变量末尾加上下划线表示这是一个影子(克隆)变量。

总结

我个人认为今天的题目出得不错,初学者很有必要亲自动手做一下。因为在做题的过程当中我们可以很具体地学到方向数组这个很有用的解题技巧,它在搜索问题当中广泛使用,可以说是做算法题必须会的技巧之一。

可能你会觉得我们通过边界判断是否需要转向的逻辑看起来有些复杂,这并不是必须的。我们也可以使用一些其他方法来代替,比如我们可以开辟一个数组记录已经遍历过的位置来代替边界的判定,和使用边界判定的方法相比,这样做消耗的空间要更大一些,并且通过边界判定的方法更加考验思维一些,因此我个人比较推荐。

好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力。

上期推文:

LeetCode1-50题汇总,速度收藏!

LeetCode刷题实战51:N 皇后

LeetCode刷题实战52:N皇后 II

LeetCode刷题实战53:最大子序和

leetcode刷题记录(六十二)——54. 螺旋矩阵 54. 螺旋矩阵 - 力扣(LeetCode)54. 螺旋矩阵 - 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 阅读详情

相关推荐

【中等】力扣算法题解析LeetCode54:螺旋矩阵

本文介绍了一种模拟顺时针螺旋遍历矩阵的算法。通过维护四个动态边界(上、下、左、右),依次处理矩阵的外层元素后向内收缩边界,直至覆盖所有元素。算法时间复杂度为O(m×n),空间复杂度O(1)(不含结果存储)。Java实现中预分配结果列表容量,并通过循环条件确保无重复访问。该解法高效直观,适用于任意m×n矩阵的螺旋遍历需求。

ylumwd的博客 926

螺旋矩阵!

#include<iostream> #include<iomanip> using namespace std; #define max 100 void show(int a[][max],int m) { for(int i=0;i<m;i++) { for(int j=0;j<m;j++) cout<<setw(5)<<a[i][j]; cout<<endl; } } void main() { .

CTFNightG的博客 307

vue微前端qiankun框架学习到项目实战,基座登录动态菜单及权限控制

技术无关,独立开发,独立部署,增量升级,独立运行,微前端的核心目标是将巨石应用拆解成若干可以自治的松耦合微应用。

前端开发工程师 9747

leetcode笔记总结——(14)螺旋数组(python编写)

力扣题目链接 目录1、题目描述:2、实现思路:3、代码描述: 1、题目描述: 2、实现思路: 直接模拟矩阵的生成。按照要求,初始位置设为矩阵的左上角,初始方向设为向右。若下一步的位置超出矩阵边界,或者是之前访问过的位置,则顺时针旋转,进入下一个方向。如此反复直至填入 n2n^2n2个元素。 我是这么标记的:首先上、下、左、右,各标记一个变量,每循环一圈,左和上加一,而右和下则减一。 注意边界:(1)当n=1时,单独判断;(2)n为奇数时,最中间的一个数要单独填充。 3、代码描述: clas.

Ma Sizhou 384

Spring Boot 实现多图片上传并回显,涨姿势了~

上传 Controller的代码非常简单,由于用了SpringMVC框架,所以直接用MultipartFile来接即可。由于是多图片上传所以用数组来接。此处应该注意参数名应该和<input>中的name值相对应: @RequestMapping("/pic") @ResponseBody publicResponseEntity<String>pic(MultipartFile[]pictures)throwsException{ ResponseEnti...

weixin_54556126的博客 893

Android GNSS 模块分析(三)JNI 层

Android GNSS;定位服务;GPS;NMEA协议;LocationManagerService;导航;

Yang_Mao_Shan的博客 5156

python螺旋数字矩阵

python螺旋数字矩阵

qq_36292545的博客 1335

freeswitch之呼叫中心acd模块开发

一、定义: ACD(Automatic Call Distributor) 自动呼叫分配,也叫智能选择座席。它是呼叫中心整个前台接入系统逻辑功能的描述:把接入的呼叫转接到正确的座席员桌前。ACD是现代呼叫中心有别于一般的热线电话系统和自动应答系统的重要标志,其性能的优劣直接影响到呼叫中心的效率和顾客的满意度。 二、ACD包含的功能点: 1 、程控交换功能 ACD在本质上也是交换机的一种类型,必须具有程控交换最基本的话务交换功能。 2 、排队功能 ACD必须具有话务排队的功能,所谓排队是指在内线都

飞鸟的博客 1870

【Leetcode】59. 螺旋矩阵 II

题目描述: 给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 示例: 输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] 解题思路: 螺旋矩阵的问题就是把1-&gt;n*n的序列依次填进矩阵中。都是从最外层填到最内层。 AC代码: class Solution { publ...

EasonWong的博客 421

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的体育赛事目标检测系统(Python+PySide6界面+训练代码)

本文详细介绍了一个基于YOLOv5/v6/v7/v8的体育赛事目标检测系统的设计与实现。系统采用先进的深度学习算法,结合PySide6图形界面,实现了对体育赛事中运动员、球类、裁判等多种目标的实时检测与跟踪。本文将全面阐述系统的架构设计、算法原理、训练流程、界面实现以及实际应用效果,并提供完整的代码实现。

YOLO 509

PCL 基于超体素的点云分割【2024最新版】

点云超体素分割原理介绍、代码实现以及如何做到将每一个超体素内的点进行单独保存而不造成点云缺失的方法。博客长期更新,本文最近一次更新时间为:2024年12月29日。

点云侠的博客 36万+

【力扣刷题&知识点总结】54螺旋矩阵Ⅰ

力扣螺旋打印实现思路与代码

qq_51565934的博客 1019

3D打印机控制系统设计:基于MATLAB的3D打印机运动学建模、轨迹规划和控制

控制实现:在控制实现中,需要将轨迹规划的结果转化为实际的控制指令,控制3D打印机按照规划的轨迹进行运动。3D打印机的运动学建模:3D打印机的运动学建模是指将3D打印机的机械结构、传动系统和运动控制部件等抽象成数学模型,以便于进行控制系统的设计和分析。轨迹规划:轨迹规划是指根据3D模型的几何形状和打印机的运动学模型,计算出打印机需要执行的运动轨迹,以便于实现所需的打印效果。控制实现:控制实现是指将轨迹规划的结果转化为控制指令,控制3D打印机按照规划的轨迹进行运动。

走向CTO的路上... 2473

力扣第 54 题: 螺旋矩阵

要求从矩阵的左上角开始,按顺时针方向逐层遍历矩阵中的所有元素,并以一维数组的形式返回结果。解决,通过维护矩阵的边界(上下左右四个方向)来实现螺旋顺序的输出。力扣第 54 题 ——测试用例中定义了一个。

weixin_48941116的博客 1105

C++多线程 task--std::promise和std::future

本文主要讲解C++11/14/17中所提供的应用于多线程编程中的Task机制。Task可由如下几部分取得而本文主要讲解std::promise和std::future相关的内容。std::promise和std::future通过一个数据管道进行交流,可以将std::promise看作生产者,std::future看作消费者,其两者形成如下的方式交互std::promise本身是一个模版类,通过std::promise可以像数据管道中设置value,异常和相应的通知信息。std::promise提供了如下接

qls315的博客 1818

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【LeetCode54螺旋矩阵、LeetCode59螺旋矩阵II:简单模拟(Java实现,一种思想解决两道题)】

通过模拟解决螺旋矩阵生成及遍历问题

NorthSmile的博客 868

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

LeetCode第54题_螺旋矩阵

给你一个m x n的矩阵matrix,请按照,返回矩阵中的所有元素。

qq_40263592的博客 1096

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

力扣第 54 题 **螺旋矩阵**

力扣第 54 题是题目要求按螺旋顺序遍历一个m x n的矩阵,并返回遍历的结果。

weixin_48941116的博客 761

LeetCode54题:螺旋矩阵(原创)

所谓顺时针螺旋循序就是以右->下->左->上的方式四个方向循环缩小的方式访问矩阵数据,一直到当前方向走不通为止

it_fly的专栏 786

【LeetCode刷题之路】54.螺旋矩阵&& 59.螺旋矩阵Ⅱ(螺旋矩阵问题)

就是说,给我们一个二维数组,然后我们需要按顺时针的顺序遍历二维数组,然后把每一个遍历到的数据放到一个一维数组中,最后返回这个一维数组。 思路很简单,关键是怎么控制让他顺时针去访问,什么时候向下走 什么时候向左走,什么时候向右走 等问题

iiiiiankor的博客 660

【刷题笔记7】LeetCode 54. 螺旋矩阵(数组模拟)

系列索引:【刷题笔记0】系列目录索引(持续更新 & 推荐收藏) 本题题目:LeetCode 54. 螺旋矩阵 分类:数组, 模拟 难度:中等

12 26 25 的博客 980

LeetCode第54题螺旋矩阵

题目描述 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。 解题思路 1、题意理解:顺时针螺旋顺序即是从左到右,从上到下,从右到左,从下到上 2、代码逻辑: (1)初始化矩阵的行和列,比如矩阵为3x4,即rowMin=0, rowMax=3, colMin=0, colMax=4 (2)遍历第一行,此时行不动, 列依从加1 (3)遍历最后一列,列不动,行依从加1 (4)遍历最后一行,行不动,列依从减1 (5)遍历第一列,列不动,行依从减1 代码 cl

LiuXiaoXueer的博客 936

leetcode第54题螺旋遍历矩阵解法详解

首先我定义的左边界的初始值是0,然后在指针的转向控制逻辑中遇到边界即可以转向,所以我的代码会在第一步就转向,这导致了错误,然而这个时候已经过去了两个小时,我放弃死磕了,我去看了题解,一看题解我就拍大腿,心理想:“原来是这样,太聪明了。通过对题目的观察,我发现在遍历矩阵的时候,指针的4个方向会周期变化,所以想到用4个单位移动量表示指针的移动,但是困在了不能实现这种周期变化,另外也无法控制指针去访问已经遍历过的区域,第一次尝试失败;3. 遇到困难没有找到问题的关键,并解决它。2.代码组织衔接僵硬。

Selbstvertrauen的博客 809

Leetcode刷题(54. 螺旋矩阵)

Leetcode刷题(54. 螺旋矩阵)一.题目二.代码(C)三.提交记录四.备注 一.题目 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] 输出: [1,2,3,6,9,8,7,4,5] 示例 2: [ [1, 2, 3, 4],...

Umbraner的博客 218

【LeetCode刷题】54.螺旋矩阵

目录题目:螺旋矩阵示例1:示例2:解题思路代码(Python)代码(C++) 题目:螺旋矩阵 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。 示例1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] 输出: [1,2,3,6,9,8,7,4,5] 示例2: 输入: [ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12] ] 输出: [1,2,3,4,8,12

qq_41810991的博客 197

leetcode刷题记录——螺旋矩阵

leetcode螺旋矩阵

GZW18620285024的博客 1199
上一篇: 不联网的电脑就安全?黑客:你还有风扇呢,嘿嘿~
下一篇: Java构造函数没有返回值,是怎么赋值的?
编程IT圈
博客等级 码龄6年 1130粉丝 544原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值