【算法-力扣】73.矩阵置零,一文彻底搞懂!

news2024/11/28 5:48:11

目录

一、题目描述

二、解题思路 

三、参考答案


一、题目描述

     矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

进阶:

  • 一个直观的解决方案是使用  O(mn) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗?

二、解题思路 

       我们可以创建两个布尔型标记数组,分别用来标记每一行和每一列中是否存在零元素。具体操作如下:首先遍历整个数组,当遇到元素值为0时,相应地将该元素所在的行和列在标记数组中的对应位置设为true。完成初步标记后,再次遍历原数组,利用之前设定的标记数组来更新原数组中的元素。这种方法能有效记录并处理零元素的位置。

三、参考答案

class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        // 定义两个数组来标记该行列是否有0
        boolean[] row = new boolean[m];
        boolean[] col = new boolean[n];
        // 遍历二位数组,设置行列数值的值
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 为0则所在行列标记为true
                if (matrix[i][j] == 0)
                    row[i] = col[j] = true;
            }
        }
        // 第二次遍历,根据标记数组的结果来更新原数组
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 当前遍历元素所在行列标记为true,则当前元素为0
                if (row[i] || col[j])
                    matrix[i][j] = 0;
            }
        }
    }
}

        以上其实就是使用标记数组的方法来解决矩阵置零问题。通过创建两个数组,分别记录需要置零的行和列,然后再次遍历矩阵进行置零操作,我们可以实现对原矩阵的修改。这种方法的时间复杂度为O(mn),空间复杂度为O(m+n)。其中m是矩阵的行数,n是矩阵的列数。

       那么我们怎么能不借助额外空间,来达到空间复杂度为O(1)呢?

       我们可以使用矩阵的第一行和第一列来代替方法一中的两个标记数组,以达到O(1)的额外空间。

       但是如果第一行和第一列中就有0,该怎么办呢?

       

       就比如上图矩阵,当我们遍历到[0,2]位置的时候,也就是第一行有0的位置的时候。我们用第一行第一列标记的时候,那么此时我们的操作就是matrix[0][0]=matrix[0][2] = 0。因为matrix[0][0] = 0,那么当我们根据第一行和第一列的值来对原数组置零的时候,最终结果就如下:

        显然,这是不符合要求的。导致这个问题的原因就是第一行和第一列共用了matrix[0][0],当matrix[0][0]=0的时候,我们无法得知它是标记的行还是列,还是两者都进行了标记。所以,在置零原数组的时候,我们可以不置零第一行和第一列的元素。而是在第一次遍历进行标记的时候,另外使用两个变量来标记行列是否有0。如果有0,再单独进行行列的处理。

        那么此时的代码就如下:

class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        // 定义两个变量来标记该行列是否有0,默认false,没有零
        boolean rowZero = false;
        boolean colZero = false;
        // 遍历二位数组,设置行列数值的值
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 为0则所在行列标记为true
                if (matrix[i][j] == 0) {
                    matrix[i][0] = matrix[0][j] = 0;
                    // 如果是第一行,则标记该行是否有0的标记为true
                    if (i == 0)
                        rowZero = true;
                    // 如果是第一列,则标记该列是否有0的标记为true
                    if (j == 0)
                        colZero = true;
                }
            }
        }
        // 第二次遍历,根据标记结果来更新原数组
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0)
                    matrix[i][j] = 0;
            }
        }
        // 处理第一行和第一列
        for (int i = 0; colZero && i < m; i++)
            matrix[i][0] = 0;
        for (int j = 0; rowZero && j < n; j++)
            matrix[0][j] = 0;
    }
}

       为了达到O(1)的空间复杂度,我们采用了这种优化手段。然而,这种做法却增加了代码的复杂度并降低了可读性。这证明了在编程和算法设计中,往往需要在各种因素之间做出权衡。没有完美的解决方案,关键在于如何根据实际需求做出恰当的选择与牺牲!

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

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

相关文章

网络通信的两大支柱:TCP与UDP协议详解(非常详细)零基础入门到精通,收藏这一篇就够了

在构建现代互联网通信的基石中&#xff0c;TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;起着至关重要的作用。本文将深入探讨两者的区别及应用场景。 1 TCP和UDP的共同点 传输层协议&#xff1a; TCP和UDP都是传输层协议&#xff…

生产中的 RAG:使你的生成式 AI 项目投入运营

作者&#xff1a;来自 Elastic Tim Brophy 检索增强生成 (RAG) 为组织提供了一个采用大型语言模型 (LLM) 的机会&#xff0c;即通过将生成式人工智能 (GenAI) 功能应用于其自己的专有数据。使用 RAG 可以降低固有风险&#xff0c;因为我们依赖受控数据集作为模型答案的基础&…

建筑八大员证报名一寸彩色照片要求及手机自拍方法解读

在建筑行业&#xff0c;八大员证的持有者是广受尊重的专业人士。然而&#xff0c;要成为一名合格的八大员&#xff0c;首先必须通过资格审核和报名流程。其中重要的一步就是提交一寸彩色照片&#xff0c;以确保个人信息准确无误。那么&#xff0c;你是否清楚报名时照片的要求以…

【Nacos 2.3.3支持Postgre SQL数据源配置】

Nacos 2.3.3支持Postgre SQL数据源配置 1、Nacos下载2、 插件下载&#xff1a;3、SQL脚本获取、nacos数据库创建、插件编译4、Nacos 集群搭建方式&#xff1a; 1、Nacos下载 下载地址&#xff1a; https://download.nacos.io/nacos-server/nacos-server-2.3.2.zip 或者自行在官…

sprintboot容器功能

容器 容器功能Spring注入组件的注解Component&#xff0c;Controller&#xff0c;Service&#xff0c;Repository案例演示 Configuration应用实例传统方式使用Configuration 注意事项和细节 Import应用实例 ConditionalConditional介绍应用实例 ImportResource应用实例 配置绑定…

图论(一)之概念介绍与图形#matlab

图论&#xff08;一&#xff09;之概念介绍与图形目录 前言 一、图论介绍 二、基本概念 2.1图的概念 2.2图形分类 2.3邻接矩阵 2.3.1无向图 2.3.2有向图 2.3.3有向赋权图 2.4出度&#xff08;Outdegree&#xff09; 2.5入度&#xff08;Indegree&#xff09; 3.四种…

【微信小程序开发实战项目】——如何去申请腾讯地图账号和在微信公众平台,配置request路径和添加地图插件

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

Day03 链表概念与单向不循环链表的实现

目录 1、顺序表的优缺点 2、链式存储的线性表 3、单向不循环链表实现 1、顺序表的优缺点 顺序表的优点是: 由于顺序表数据元素的内存地址都是连续的,所以可以实现随机访问,而且不需要多余的信息来描述相关的数据,所以存储密度高。 顺序表的缺点是: 顺序表的数据在进行…

windows下的eclipse按Ctrl+Shift+F格式化代码不起作用的处理

1、先上张图&#xff1a; 上面Format&#xff1a;CtrlShiftF&#xff0c;按了以后不起作用。 2、这个快捷键不起作用的原因&#xff1a;可能是快捷键冲突了。 机器上装了Sougou输入法&#xff0c;将输入法切换为英文模式是起作用的。 那么应该就是这个原因了。 3、解决方法…

甄嬛传熹贵妃上户口:如果让他陪你过冬天,那朕能不能睡中间?贝叶斯模型推导爸爸去哪儿

关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业分析/数据结构与算法学习资料 背景 《甄嬛传》是大家耳熟能详的宫廷剧&#xff0c;其中复杂的宫斗情节和深刻的人物刻画让人津津乐道。甄嬛因为与皇帝(四郎)闹翻了&#xff0c;去甘露寺待了一段时间&#x…

【数据结构】遍历二叉树(递归思想)-->赋源码

欢迎来到我的Blog&#xff0c;点击关注哦&#x1f495; 前言 二叉树遍历是指按照一定的顺序访问二叉树中的每个节点&#xff0c;使得每个节点恰好被访问一次。遍历是二叉树上最重要的运算之一&#xff0c;是二叉树上进行其他运算的基础。 一、二叉树遍历概念 二叉树遍历分类 …

【机器学习】LightGBM: 优化机器学习的高效梯度提升决策树

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 LightGBM: 优化机器学习的高效梯度提升决策树引言一、LightGBM概览二、核心技术…

微服务开发与实战Day08 - Elasticsearch

一、初始Elasticsearch 高性能分布式搜索引擎 1. 认识和安装 1.1 认识 Lucene是一个Java语言的搜索引擎类库&#xff0c;是Apache公司的顶级项目&#xff0c;由DougCutting于1999年研发。官网地址&#xff1a;Apache Lucene - Welcome to Apache Lucene Lucene的优势&…

誉天教育近期开班计划(6月15日更新)

云计算HCIP 周末班 2024/6/15 田老师 售前IP-L3 周末班 2024/6/15 陈老师 RHCA442 晚班 2024/6/17邹老师 数通HCIE 晚班 2024/6/24阮老师 云计算HCIE直通车晚班 2024/6/25 曾老师 售前IT-L3 周末班 2024/6/29 伍老师 数通HCIP 晚班 2024/7/1杨老师 存储直通车 晚班 2024/7/1 高…

【ARMv8/ARMv9 硬件加速系列 3 -- SVE 指令语法及编译参数详细介绍】

文章目录 SVE 汇编语法SVE 单通道谓词SVE 测试代码 SVE 软件和库支持SVE 编译参数配置-marcharmv8-alseprofilememtagsve2-aessve2-bitpermcryptosve2sve2-sha3sve2-sm4 SVE 汇编语法 在介绍 SVE 汇编指令语法之前&#xff0c;先介绍下如何判断自己所使用的芯片是否实现了SVE功…

算法01 递推算法及相关问题详解【C++实现】

目录 递推的概念 训练&#xff1a;斐波那契数列 解析 参考代码 训练&#xff1a;上台阶 参考代码 训练&#xff1a;信封 解析 参考代码 递推的概念 递推是一种处理问题的重要方法。 递推通过对问题的分析&#xff0c;找到问题相邻项之间的关系&#xff08;递推式&a…

践行国产化替代,优刻得私有云勇当先锋

编辑&#xff1a;阿冒 设计&#xff1a;沐由 阳泉&#xff0c;十万火急&#xff01; 位于太行山西麓的山西省阳泉市&#xff0c;是一座历史悠久、底蕴深厚、资源丰富的名城&#xff0c;拥有超百万常住人口&#xff0c;国内生产总值在2022年成功跨越千亿元大关。然而&#xff0c…

leetcode 56合并区间

思路 合并就是首先应该按照left左边界排序&#xff0c;排完序以后&#xff0c;如果i的左边界小于等于i-1的右边界&#xff0c;说明有重合&#xff0c;此时这两个可以合并&#xff0c;右边界应该取最大值。 代码 排序 我是定义了一个类,存储左右边界&#xff0c;先将数组转化…

传输层udp和tcp协议格式

UDP协议 UDP协议端格式 udp的前八个字节是报头&#xff0c;后面部分就是有效载荷。而目的端口号就保证了udp向应用层交付的问题。 而针对于报头和有效载荷分离是根据固定八字结的报头长度。数据的长度就是取决于报头中udp长度字段的大小来确定udp报文长度&#xff0c;因此也可…

【Matlab编程学习】 | matlab语言编程基础:常用图形绘制基础学习

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…