力扣第 73 题 矩阵置零

题目描述

给定一个 m x n 的矩阵 matrix,其中每个元素不是 0 就是非零整数。

如果一个元素是 0,则将它所在的整行和整列都置为 0。请你实现这个操作,要求 空间复杂度 O(1)


示例

示例 1:

输入

matrix = [
  [1,1,1],
  [1,0,1],
  [1,1,1]
]

输出

[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

输入

matrix = [
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]

输出

[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

解题思路

1. 暴力法

  • 最直观的做法是,遍历整个矩阵,遇到 0 时,标记该位置所在的行和列,并将这些行和列的所有元素设置为 0。
  • 这种方法的空间复杂度是 O(m + n),因为我们需要额外的数组来记录需要置零的行和列。

2. 空间优化(O(1) 空间复杂度)

  • 题目要求空间复杂度是 O(1),即不能使用额外的数组(如布尔数组)来存储行和列的状态。我们可以在原地进行修改。
  • 通过使用矩阵的 第一行第一列 来记录该行和该列是否需要置零。
  • 第一行第一列 本身也可能包含零,所以需要额外的变量来记录它们是否需要置零。

3. 优化步骤

  1. 检查第一行和第一列:我们需要一个标志来记录第一行和第一列是否应该被置零。
  2. 遍历矩阵:从矩阵的第二行和第二列开始,如果 matrix[i][j] == 0,就将 matrix[i][0]matrix[0][j] 设置为 0,表示该行和列应该被置零。
  3. 根据标志置零:根据第一行和第一列的标记,更新矩阵中的其它元素。
  4. 处理第一行和第一列:最后根据记录的标志更新第一行和第一列。

实现代码:

#include <stdio.h>

void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
    int m = matrixSize; // 矩阵的行数
    int n = *matrixColSize; // 矩阵的列数

    int firstRowZero = 0, firstColZero = 0;

    // 检查第一行是否需要置零
    for (int j = 0; j < n; j++) {
        if (matrix[0][j] == 0) {
            firstRowZero = 1;
            break;
        }
    }

    // 检查第一列是否需要置零
    for (int i = 0; i < m; i++) {
        if (matrix[i][0] == 0) {
            firstColZero = 1;
            break;
        }
    }

    // 使用第一行和第一列标记其他行列需要置零
    for (int i = 1; i < m; i++) {
        for (int j = 1; j < n; j++) {
            if (matrix[i][j] == 0) {
                matrix[i][0] = 0; // 标记该行
                matrix[0][j] = 0; // 标记该列
            }
        }
    }

    // 根据标记的行列置零
    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;
            }
        }
    }

    // 处理第一行
    if (firstRowZero) {
        for (int j = 0; j < n; j++) {
            matrix[0][j] = 0;
        }
    }

    // 处理第一列
    if (firstColZero) {
        for (int i = 0; i < m; i++) {
            matrix[i][0] = 0;
        }
    }
}

int main() {
    int m = 3, n = 4;
    
    // 动态分配内存
    int** matrix = (int**)malloc(m * sizeof(int*));
    for (int i = 0; i < m; i++) {
        matrix[i] = (int*)malloc(n * sizeof(int));
    }

    // 初始化矩阵
    int matrixData[3][4] = {
        {0, 1, 2, 0},
        {3, 4, 5, 2},
        {1, 3, 1, 5}
    };

    // 将数据复制到动态分配的矩阵中
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i][j] = matrixData[i][j];
        }
    }

    setZeroes(matrix, m, &n);

    // 打印结果
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    // 释放内存
    for (int i = 0; i < m; i++) {
        free(matrix[i]);
    }
    free(matrix);

    return 0;
}

步骤说明:

  1. 检查第一行和第一列是否需要置零:
    • 使用变量 firstRowZerofirstColZero 来分别标记第一行和第一列是否包含零。
  2. 遍历矩阵并标记需要置零的行和列:
    • 从第二行第二列开始,遍历矩阵。如果遇到 matrix[i][j] == 0,就将 matrix[i][0]matrix[0][j] 设置为零,表示第 i 行和第 j 列需要置零。
  3. 根据标记的行列更新矩阵:
    • 再次遍历矩阵,按照第一行和第一列的标记将相应位置的元素置零。
  4. 处理第一行和第一列:
    • 如果 firstRowZero 为 1,则将第一行所有元素置零。
    • 如果 firstColZero 为 1,则将第一列所有元素置零。

时间复杂度与空间复杂度

时间复杂度:

  • 遍历矩阵两次,因此时间复杂度是 O(m * n),其中 mn 分别是矩阵的行数和列数。

空间复杂度:

  • 我们仅使用了常量的额外空间(firstRowZerofirstColZero),因此空间复杂度是 O(1),符合题目要求。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubantu系统docker运行成功拉取失败【成功解决】

解决docker运行成功拉取失败 失败报错 skysky-Legion-Y7000-IRX9:~$ docker run hello-world docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head “http://%2Fvar%2Frun%2Fdocker.sock/_ping”: dial uni…

git rebase-优雅合并与修改提交

文章目录 简介rebase用于合并使用rebase修改提交cherry-pick 简介 在Git核心概念图例与最常用内容操作(reset、diff、restore、stash、reflog、cherry-pick)中我们已经介绍了git的最常用实用的命令。 在上面说的那篇文章中&#xff0c;我们只是简单提了一下rebase。 是因为r…

TongRDS分布式内存数据缓存中间件

命令 优势 支持高达10亿级的数据缓冲&#xff0c;内存优化管理&#xff0c;避免GC性能劣化。 高并发系统设计&#xff0c;可充分利用多CPU资源实现并行处理。 数据采用key-value多索引方式存储&#xff0c;字段类型和长度可配置。 支持多台服务并行运行&#xff0c;服务之间可互…

【大数据学习 | Spark调优篇】Spark之内存调优

1. 内存的花费 1&#xff09;每个Java对象&#xff0c;都有一个对象头&#xff0c;会占用16个字节&#xff0c;主要是包括了一些对象的元信息&#xff0c;比如指向它的类的指针。如果一个对象本身很小&#xff0c;比如就包括了一个int类型的field&#xff0c;那么它的对象头实…

pageoffice最新版本浏览器点击没反应解决办法

一、问题现象 最新版本的谷歌、火狐浏览器&#xff0c;调用pageoffice时&#xff0c;点击后没反应&#xff08;旧的谷歌浏览器不受影响&#xff09;。 二、产生原因 服务器返回pageOffice的客户端唤起链接格式为&#xff1a; PageOffice://|http://192.168.1.120:8080/xxx …

知行合一:实践中的技术分享与学习

随着科技的不断发展&#xff0c;技术的更新迭代也在不断加速。在这个信息化、数字化的时代&#xff0c;技术人员之间的交流与合作显得尤为重要。为了帮助广大技术爱好者、从业者和专家们相互学习、分享经验、解决技术难题&#xff0c;涵盖了数据库、容器化技术、运维、研发、网…

使用经典的Java,还是拥抱新兴的Rust?

在当代互联网时代的企业级开发中&#xff0c;技术栈的选择往往牵动着每个团队的神经。随着Rust语言的崛起&#xff0c;许多开发团队开始重新思考&#xff1a;是继续坚持使用经典的Java&#xff0c;还是拥抱新兴的Rust&#xff1f;这个问题背后&#xff0c;折射出的是对技术演进…

【Qt】图片绘制不清晰的问题

背景 实现一个图片浏览器&#xff0c;可以支持放大/缩小查看图片。主要组件如下&#xff1a; // canvaswidget.h #ifndef CANVASWIDGET_H #define CANVASWIDGET_H#include <QWidget>class CanvasWidget : public QWidget {Q_OBJECT public:explicit CanvasWidget(QImag…

vscode 怎么下载 vsix 文件?

参考&#xff1a;https://marketplace.visualstudio.com/items?itemNameMarsCode.marscode-extension 更好的办法&#xff1a;直接去相关插件的 github repo 下载老版本 https://github.com/VSCodeVim/Vim/releases?page5 或者&#xff0c;去 open-vsx.org 下载老版本 点击这…

学习笔记043——HashMap源码学习1

文章目录 1、HashMap2、Hashtable3、TreeMap4、HashMap 底层结构4.1、什么是红黑树&#xff1f; 1、HashMap HashMap key 是不能重复的&#xff0c;value 可以重复 底层结构 key-value 进行存储&#xff0c;key-value 存入到 Set 中&#xff0c;再将 Set 装载到 HashMap pack…

火语言RPA流程组件介绍--键盘按键

&#x1f6a9;【组件功能】&#xff1a;模拟键盘按键 配置预览 配置说明 按键 点击后,在弹出的软键盘上选择需要的按键 执行后等待时间(ms) 默认值300,执行该组件后等待300毫秒后执行下一个组件. 输入输出 输入类型 万能对象类型(System.Object)输出类型 万能对象类型…

电子应用设计方案-30:智能扫地机器人系统方案设计

智能扫地机器人系统方案设计 一、引言 随着人们生活节奏的加快和对生活品质的追求&#xff0c;智能家居产品越来越受到消费者的青睐。智能扫地机器人作为一种能够自动清扫地面的智能设备&#xff0c;为人们节省了大量的时间和精力。本方案旨在设计一款功能强大、智能化程度高、…

从简单的自动化脚本到复杂的智能助手:Agent技术的实践与应用

现代软件开发中&#xff0c;Agent技术正在悄然改变着我们构建应用程序的方式。一个Agent就像是一个能独立完成特定任务的智能助手&#xff0c;它可以感知环境、作出决策并采取行动。让我们通过实际案例&#xff0c;深入了解如何运用Agent技术来构建智能系统。 想象你正在开发一…

Ubuntu Server 22.04.5 从零到一:详尽安装部署指南

文章目录 Ubuntu Server 22.04.5 从零到一&#xff1a;详尽安装部署指南一、部署环境二、安装系统2.1 安装2.1.1 选择安装方式2.1.2 选择语言2.1.3 选择不更新2.1.4 选择键盘标准2.1.5 选择安装版本2.1.6 设置网卡2.1.7 配置代理2.1.8 设置镜像源2.1.9 选择装系统的硬盘2.1.10 …

定时/延时任务-ScheduledThreadPoolExecutor的使用

文章目录 1. 概要2. 固定速率和固定延时2.1 固定速率2.2 固定延时 3. API 解释3.1 schedule3.2 固定延时 - scheduleWithFixedDelay3.2 固定速率 - scheduleWithFixedDelay 4. 小结 1. 概要 前三篇文章的地址&#xff1a; 定时/延时任务-自己实现一个简单的定时器定时/延时任…

Linux操作系统学习---初识环境变量

目录 ​编辑 环境变量的概念&#xff1a; 小插曲&#xff1a;main函数的第一、二个参数 获取环境变量信息&#xff1a; 1.main函数的第三个参数 2.查看单个环境变量 3.c语言库函数getenv() 和环境变量相关的操作指令&#xff1a; 1.export---导出环境变量&#xff1a; 2.unse…

husky,commit规范,生成CHANGELOG.md,npm发版

项目git提交工程化&#xff08;钩子&#xff0c;提交信息commit message&#xff09;&#xff0c;npm修改版本&#xff0c;需要涉及到的包&#xff1a; husky&#xff0c;允许在git钩子中执行不同的脚步&#xff0c;如commitlint&#xff0c;eslint&#xff0c;prettier&#…

基于Python的飞机大战复现

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【趣味】斗破苍穹修炼文字游戏HTML,CSS,JS

目录 图片展示 游戏功能 扩展功能 完整代码 实现一个简单的斗破苍穹修炼文字游戏&#xff0c;你可以使用HTML、CSS和JavaScript结合来构建游戏的界面和逻辑。以下是一个简化版的游戏框架示例&#xff0c;其中包含玩家修炼的过程、增加修炼进度和显示经验值的基本功能。 图片…

005 MATLAB符号微积分

前言&#xff1a; 在MATLAB中&#xff0c;数值与符号的主要区别在于它们的处理方式和应用场景 数值计算适用于实际的数值计算问题&#xff0c;如矩阵运算、数据分析等。符号计算适用于符号推导、公式化简和符号解析&#xff0c;如理论物理和工程计算。 01 符号对象 1.基本符…