顺时针打印矩阵:偏移量法与边界控制法比较---剑指offer-JZ29 顺时针打印矩阵

news2024/9/30 5:27:56

 在编程中,处理二维数组的问题可以有多种解法。今天,我们将探讨两种解决“顺时针打印矩阵”问题的方法:偏移量法边界控制法,并进行比较。

题目

题目连接:顺时针打印矩阵_牛客题霸_牛客网 (nowcoder.com)

偏移量法

偏移量法的核心思想是使用两个数组来控制遍历方向。这种方法特别适合于遍历二维空间时的方向控制。

代码实现

import java.util.ArrayList;
import java.util.List;

public class Solution {
    // 定义dx和dy为静态数组,表示四个方向的偏移量:上,右,下,左
    private static final int[] dx = {-1, 0, 1, 0};
    private static final int[] dy = {0, 1, 0, -1};

    public List<Integer> printMatrix(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return res;

        int n = matrix.length, m = matrix[0].length;
        boolean[][] st = new boolean[n][m]; // st数组用于标记已访问的位置

        int x = 0, y = 0, d = 1; // 初始位置(0,0)和方向(向右)
        for (int k = 0; k < n * m; k++) {
            res.add(matrix[x][y]); // 添加当前元素
            st[x][y] = true; // 标记为已访问

            // 计算下一个位置
            int a = x + dx[d], b = y + dy[d];
            // 判断边界和是否已访问
            if (a < 0 || a >= n || b < 0 || b >= m || st[a][b]) {
                d = (d + 1) % 4; // 改变方向
                a = x + dx[d];
                b = y + dy[d];
            }
            x = a;
            y = b;
        }
        return res;
    }
}

解释:

偏移量按照“上、右、下、左”的顺序来定义的。这个顺序决定了遍历矩阵的方向。

在代码中:

  • dx = {-1, 0, 1, 0} 表示行的变化。

  • dy = {0, 1, 0, -1} 表示列的变化。

这里的偏移量对应的遍历方向是:

  1. 向上(dx = -1, dy = 0)。

  2. 向右(dx = 0, dy = 1)。

  3. 向下(dx = 1, dy = 0)。

  4. 向左(dx = 0, dy = -1)。

在遍历过程中,通过改变d的值来选择不同的偏移量,从而改变遍历的方向。遍历始于向右方向(d = 1),并在遇到边界或已访问的元素时顺时针旋转到下一个方向。

这种方法特别适合处理这类二维数组遍历的问题。通过简单地调整偏移量数组,可以轻松地更改遍历的方向或模式,适应各种不同的需求和场景。

如何定义dx、dy数组?

矩阵遍历使用的xy的定义有些特殊。通常,在数学和计算机图形学中,我们习惯于将x轴定义为水平方向,y轴定义为垂直方向。然而,在二维数组或矩阵的上下文中,这些轴的定义通常与传统的笛卡尔坐标系有所不同。

在代码中

  • x变量代表的是二维数组的行索引。

  • y变量代表的是二维数组的列索引。

然而,

  • 当我们说“向上”移动时,实际上是在减少x的值(因为在数组中向上移动意味着向更小的行索引移动)。

  • 同样,"向右"移动实际上是增加y的值(在数组中向右移动意味着向更大的列索引移动)。

  • “向下”移动是增加x的值。

  • “向左”移动是减少y的值。

这种定义方式是基于二维数组的索引,其中matrix[x][y]表示位于第x行和第y列的元素。所以,尽管这种定义方式可能与传统的笛卡尔坐标系不同,但它完全适合于二维数组或矩阵的遍历操作。

我的这篇  使用邻接点偏移量数组解决 BFS 类问题-CSDN博客  博客同样讲解了这类问题

优势与局限性

优势

  1. 代码简洁:整个遍历过程可以在一个循环中完成。

  2. 方向控制灵活:通过改变索引即可改变方向,适用于复杂路径的遍历。

局限性

  1. 需要额外状态数组:用于记录哪些元素已被访问。

  2. 边界处理稍复杂:需要检查下一个位置是否越界或已访问。


边界控制法

边界控制法通过定义上下左右边界来控制遍历过程。

代码实现

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> res = new ArrayList<>();
         //先排除特殊情况
        if(matrix.length == 0) {
            return res;
        }
        //左边界
        int left = 0; 
        //右边界
        int right = matrix[0].length - 1; 
        //上边界
        int up = 0; 
        //下边界
        int down = matrix.length - 1; 
        //直到边界重合
        while(left <= right && up <= down){ 
            //上边界的从左到右
            for(int i = left; i <= right; i++) 
                res.add(matrix[up][i]); 
            //上边界向下
            up++; 
            if(up > down)
                break;
            //右边界的从上到下
            for(int i = up; i <= down; i++) 
                res.add(matrix[i][right]);
            //右边界向左
            right--; 
            if(left > right)
                break;
            //下边界的从右到左
            for(int i = right; i >= left; i--) 
                res.add(matrix[down][i]);
            //下边界向上
            down--; 
            if(up > down)
                break; 
            //左边界的从下到上
            for(int i = down; i >= up; i--) 
                res.add(matrix[i][left]);
            //左边界向右
            left++; 
            if(left > right)
                break;
        }
        return res;
    }
}

优势与局限性

优势

  1. 直观明了:逻辑清晰,易于理解和维护。

  2. 无需额外状态数组:直接通过边界控制实现遍历。

局限性

  1. 多个循环:每个方向的遍历需要独立的循环。

  2. 边界更新逻辑:每完成一个方向,都需要更新边界。

总结

两种方法各有优缺点。偏移量法在代码简洁性和灵活性方面更优,但需要额外的状态数组来跟踪已访问的元素。边界控制法则在逻辑清晰度上占优,但涉及多个循环和边界更新的逻辑。

就我各个人来讲。把算法题抽象成通用模板确实可以提高解题效率,特别是对于那些有固定模式或可复用逻辑的问题。使用偏移量方法解决矩阵遍历类问题是一个很好的例子。这种方法不仅提供了一种清晰、灵活的方式来处理二维空间的遍历,还可以轻松应对多种不同的遍历要求,比如螺旋遍历、波形遍历等。

偏移量法的模板化

偏移量法的核心在于定义一组方向向量,通过这些向量控制遍历的方向。这种方法的模板化可以分为以下几个步骤:

  1. 定义方向向量:创建两个数组,一个表示行的偏移(dx),另一个表示列的偏移(dy)。例如,对于上、右、下、左的顺时针方向,可以定义dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1}

  2. 初始化遍历状态:设置起始点和初始方向,通常从(0,0)点开始,方向设置为向右。

  3. 遍历矩阵:使用一个循环进行遍历,每次移动后检查边界和是否已访问,必要时改变方向。

  4. 边界和访问状态检查:在每次移动后,检查下一个位置是否超出矩阵边界或者已经访问过。如果是,改变方向。

这种模板化方法在处理各种矩阵遍历问题时具有明显优势:

  • 可重用性:一旦掌握了这个模板,就可以快速应用到类似的问题上。
  • 灵活性:通过调整方向向量,可以轻松适应不同的遍历要求。
  • 简洁性:代码更加简洁,易于理解和维护。

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

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

相关文章

枚举类型有着一篇足以

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;橘橙黄又青-CSDN博客 1.关键字enum的定义 enum是C语言中的一个关键字&#xff0c;enum叫枚举数据类型&#…

Unity 编辑器篇|(十三)自定义属性绘制器(PropertyDrawer ,PropertyAttribute) (全面总结 | 建议收藏)

目录 1. 前言2. PropertyDrawer2.1 参数总览2.2 两种用途2.3 注意事项2.4 代码样例 3. PropertyDrawer与PropertyAttribute结合使用 1. 前言 在Unity中&#xff0c;PropertyDrawer和PropertyAttribute是两个重要的工具&#xff0c;它们主要用于自定义属性的显示和行为。Proper…

ipv6-ipv4隧道和bgp全网通小实验

效果图:r1能ping通r11和r8,r8能ping通r11 个人理解:ipv6-ipv4隧道只认前缀,例如:r2隧道的source是其接口g0/0/1,它的ipv4 address是29.1.1.1/24,那么转化过来的ipv6就是2002:1d01:0101::/48,对端的r10只能ping通2002:1d01:0101::/48网段内的ipv6。 同理,r10隧道的source是其接…

代理设计模式JDK动态代理CGLIB动态代理原理

代理设计模式 代理模式&#xff08;Proxy&#xff09;&#xff0c;为其它对象提供一种代理以控制对这个对象的访问。如下图 从上面的类图可以看出&#xff0c;通过代理模式&#xff0c;客户端访问接口时的实例实际上是Proxy对象&#xff0c;Proxy对象持有RealSubject的引用&am…

qml定位器:Row、Column、Grid、Flow

03.qml import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("2.7 定位器")Column {RedSquare {}RedSquare {}RedSquare {}spacing: 10 //间隔}Row {RedSquare {}RedSquare {}RedSquare {}spacing: 10x: 58}Flow { //中文是“流”的意思&#xff…

特征融合篇 | YOLOv8 引入长颈特征融合网络 Giraffe FPN

在本报告中,我们介绍了一种名为DAMO-YOLO的快速而准确的目标检测方法,其性能优于现有的YOLO系列。DAMO-YOLO是在YOLO的基础上通过引入一些新技术而扩展的,这些技术包括神经架构搜索(NAS)、高效的重参数化广义FPN(RepGFPN)、带有AlignedOTA标签分配的轻量级头部以及蒸馏增…

【大数据】流处理基础概念(一):Dataflow 编程基础、并行流处理

流处理基础概念&#xff08;一&#xff09;&#xff1a;Dataflow 编程基础、并行流处理 1.Dataflow 编程基础1.1 Dataflow 图1.2 数据并行和任务并行1.3 数据交换策略 2.并行流处理2.1 延迟与吞吐2.1.1 延迟2.1.2 吞吐2.1.3 延迟与吞吐 2.2 数据流上的操作2.2.1 数据接入和数据…

企业网架构

企业网架构 局域网通信不同网段 局域网通信 MAC地址&#xff1a;硬件地址&#xff0c;固定在网卡上的地址(唯一标识一个网卡)&#xff0c;确定网络设备位置的,数据链路层。一个设备可以有多个网卡&#xff0c;每一个网卡都需要一个唯一MAC。ARP协议&#xff1a;通过目的IP&…

回归预测 | Matlab实现GA-APSO-MBP、GA-MBP、MBP、BP多输入单输出回归预测

回归预测 | Matlab实现GA-APSO-MBP、GA-MBP、MBP、BP多输入单输出回归预测 目录 回归预测 | Matlab实现GA-APSO-MBP、GA-MBP、MBP、BP多输入单输出回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现GA-APSO-MBP、GA-MBP、MBP、BP多输入单输出回归预测&…

图片如何转文字?手把手教你图片转文字

面对日益增长的数字化信息&#xff0c;图片转文字成为了一种必不可少的技术&#xff0c;通过简单的步骤&#xff0c;将图片中的文字转换为可编辑和可搜索的文本&#xff0c;提高工作效率和准确性。 这是一款通过光学字符识别&#xff08;OCR&#xff09;实现从图像中提取文字的…

细数2023测试测量及通信行业的十大年度热点动态

2023年&#xff0c;全球测试测量及通信行业在多重技术革新和市场需求的驱动下呈现出强劲的增长态势。这一年里&#xff0c;5G通信网络的大规模部署与商用、人工智能技术的广泛应用、物联网&#xff08;IoT&#xff09;设备数量的爆炸性增长以及电动汽车行业的迅猛发展等因素&am…

在CentOS 7 中配置NFS服务器

目录 1、克隆两个虚拟机 2、安装 NFS 服务 3、NFS 服务使用 1、克隆两个虚拟机 nfs-servernfs-client&#xff08;修改ip地址&#xff09;[rootxnode1 ~]# cd /etc/sysconfig/network-scripts/[rootxnode1 network-scripts]# vi ifcfg-eno16777736 #修改内容如下 BOOTPROT…

浅析Java虚拟机中的ZGC

引言 为什么需要垃圾回收&#xff08;Garbage Collection&#xff09; 垃圾回收是Java开发中的关键机制&#xff0c;负责自动管理内存&#xff0c;防止内存泄漏&#xff0c;提高开发效率和应用程序的稳定性。 Java中主要的垃圾回收方法 标记-清除算法&#xff08;Mark and …

YZ系列工具之YZ05:代码运行中调用“计算器”

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套一部VBA手册&#xff0c;教程分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的…

CentOS搭建DNS服务器

服务器规划 DNS服务器IP为&#xff1a;172.16.32.253 需要自定义域名解析 172.16.32.253 dns.zhangsan.com 172.16.32.128 test1.zhangsan.com 172.16.32.129 test2.zhangsan.com 172.16.32.130 www.zhangsan.com 1. 服务器初始化 [rootlocalhost ~]# hostnamectl set-hostnam…

python|写一个简单的web应用框架

写应用框架需要写底层服务器么? 这个要区分2种情况&#xff0c;如果应用框架&#xff0c;你没有参考WSGI标准&#xff0c;那么在写应用框架之前&#xff0c;你就必须要定义一套属于自己的服务器&#xff0c;当然本文不采取这种方式&#xff0c;专业的事情应该专业的人来做。我…

springboot集成easypoi

easypoi,主打的功能就是容易,通过简单的配置&#xff0c;就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出 pom导入依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…

实现钉钉与宁波银行对接,助力东吴黄金集团财务智能化

客户介绍&#xff1a; 某黄金集团有限公司是一家在国内外黄金市场上具有重要影响力的综合性黄金企业。该公司拥有一支高素质、专业化的团队&#xff0c;具备丰富的行业经验和卓越的执行力。在业务范围上&#xff0c;该公司涵盖了黄金勘探、采选、冶炼、加工、销售等全产业链&a…

华为机考入门python3--(0)模拟题2-vowel元音字母翻译

分类&#xff1a;字符串 知识点&#xff1a; 字符串转list&#xff0c;每个字符成为list中的一个元素 list(string) 字符串变大小写 str.upper(), str.lower() 题目来自【华为招聘模拟考试】 # If you need to import additional packages or classes, please import …

一篇搞定大论文参考文献,从找文献到交叉引用全流程

我们在写论文过程中&#xff0c;肯定会引用他人的文献&#xff0c;根据自己的写作经历&#xff0c;总结了一套很实用且不会出错的引用方法。1、记录文献顺序 你在论文中每引用一篇文献&#xff0c;你就在文献后加上[1][2]…[n]&#xff0c;然后新建一个word文档&#xff0c;在…