LeetCode 热题 100 之 73.矩阵置零(含图解)

官方原始解法(容易想到)

复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        boolean[] row = new boolean[m];
        boolean[] col = new boolean[n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    row[i] = col[j] = true;
                }
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (row[i] || col[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/set-matrix-zeroes/solutions/669901/ju-zhen-zhi-ling-by-leetcode-solution-9ll7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

为了在不使用额外空间的情况下解决问题,我们可以利用矩阵的第一行和第一列作为标记,来记录哪些行和列需要被置零。同时,使用两个额外的布尔变量来记录第一行和第一列本身是否需要置零。


步骤分解

  1. 预处理标记

    • 遍历矩阵,检查第一行和第一列是否存在 0,并用 row0col0 两个布尔变量记录下来。
    • 再次遍历矩阵(从第二行第二列开始),如果发现 matrix[i][j] == 0,则将 matrix[i][0](标记第 i 行)和 matrix[0][j](标记第 j 列)置为 0。
  2. 置零操作

    • 遍历矩阵(从第二行第二列开始),如果 matrix[i][0]matrix[0][j] 为 0,则将 matrix[i][j] 置为 0。
    • 根据预处理的 row0col0 标记,最后决定是否将第一行和第一列整体置零。

画的丑请见谅


Java 代码实现

复制代码
public void setZeroes(int[][] matrix) {
    int m = matrix.length;
    int n = matrix[0].length;
    boolean row0 = false; // 标记第一行是否有0
    boolean col0 = false; // 标记第一列是否有0

    // 1. 检查第一行和第一列
    for (int j = 0; j < n; j++) {
        if (matrix[0][j] == 0) {
            row0 = true;
            break;
        }
    }
    for (int i = 0; i < m; i++) {
        if (matrix[i][0] == 0) {
            col0 = true;
            break;
        }
    }

    // 2. 用第一行和第一列标记需要置零的行和列
    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;
            }
        }
    }

    // 3. 根据标记置零(除第一行第一列外)
    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;
            }
        }
    }

    // 4. 最后处理第一行和第一列
    if (row0) {
        for (int j = 0; j < n; j++) {
            matrix[0][j] = 0;
        }
    }
    if (col0) {
        for (int i = 0; i < m; i++) {
            matrix[i][0] = 0;
        }
    }
}

复杂度分析

  • 时间复杂度:O (mn),我们对矩阵进行了多次线性遍历。
  • 空间复杂度:O (1),我们只使用了常数级别的额外空间,符合题目 "原地算法" 的要求。

这个算法的核心作用,是在不额外占用大量内存的前提下,高效地对矩阵进行 "置零" 操作,它的价值主要体现在以下几个方面:


实际作用

1. 核心作用:原地修改,节省空间

  • 空间效率:它通过复用矩阵的第一行和第一列作为 "标记位",将空间复杂度从 O (mn) 或 O (m+n) 优化到了 O (1),只使用了两个布尔变量。
  • 原地修改:直接在输入矩阵上进行修改,避免了创建一个同样大小的新矩阵,这在处理大规模数据(如高清图像、传感器矩阵、大型表格)时至关重要。

2. 典型应用场景

图像处理与计算机视觉 🖼️
  • 图像降噪 / 二值化:在处理图像矩阵时,经常需要将满足特定条件(如亮度低于阈值)的像素所在行 / 列置零。这个算法可以高效地完成这类任务,同时保持内存占用极低。
  • 特征提取:在边缘检测或特征点提取后,需要将无关的背景区域(行 / 列)清零,以突出主体。
数据清洗与预处理 📊
  • 缺失值处理:在数据分析中,矩阵中的 0 可以代表缺失值。这个算法可以快速地将包含缺失值的行和列标记并清除,为后续的机器学习模型准备干净的数据。
  • 稀疏矩阵优化:在处理稀疏矩阵时,可以通过此算法快速清理掉全零行 / 列,减少存储和计算开销。
游戏与图形学 🎮
  • 碰撞检测:在游戏开发中,矩阵可以表示游戏世界的网格。当检测到碰撞(某个元素为 0)时,需要将其所在的行和列(如障碍物)置零,以更新游戏状态。
  • 渲染优化:在 3D 渲染中,通过置零不可见的行 / 列来优化渲染管线,减少不必要的计算。
传感器与物联网 📡
  • 传感器数据过滤:在物联网设备中,矩阵可以存储来自多个传感器的时间序列数据。当某个传感器(行)或某个时间点(列)的数据异常(为 0)时,需要将其置零,以避免影响整体分析。

3. 设计思想的复用价值

这个算法体现的 "用已有空间做标记,避免额外开销" 的思想,在很多领域都有借鉴意义:

  • 内存受限系统:如嵌入式设备、移动应用,内存资源非常宝贵,任何能节省空间的技巧都至关重要。
  • 大数据处理:在分布式计算框架中,减少数据的复制和传输是提升性能的关键。
相关推荐
6Hzlia4 小时前
【Hot 100 刷题计划】 LeetCode 74. 搜索二维矩阵 | C++ 二分查找 (一维展开法)
c++·leetcode·矩阵
跨境麦香鱼4 小时前
2026 Pinterest账号运营攻略:多开养号与矩阵引流实战
大数据·人工智能·矩阵
AI科技星5 小时前
基于四维速率恒为c公设的北斗GEO卫星昼夜钟差模型修正与实测验证
开发语言·人工智能·线性代数·算法·数学建模
6Hzlia5 小时前
【Hot 100 刷题计划】 LeetCode 240. 搜索二维矩阵 II | C++ 巧妙利用单调性 (BST 法)
c++·leetcode·矩阵
Jasmine_llq1 天前
《B3865 [GESP202309 二级] 小杨的 X 字矩阵》
线性代数·矩阵·条件判断算法·枚举算法(遍历算法)·规律模拟算法
杰杰桀桀桀1 天前
4*4无时延矩阵键盘(非阻塞)--附代码链接
stm32·单片机·嵌入式硬件·矩阵·计算机外设·无时延矩阵键盘
阿Y加油吧1 天前
二分查找进阶:搜索二维矩阵 & 查找元素首尾位置 深度解析
线性代数·算法·矩阵
songyuc1 天前
【矩阵论】关于rank的几何解释:“观测者维度”
人工智能·矩阵
计算机安禾1 天前
【数据结构与算法】第33篇:交换排序(二):快速排序
c语言·开发语言·数据结构·数据库·算法·矩阵·排序算法
MediaTea2 天前
AI 术语通俗词典:矩阵乘法
人工智能·线性代数·矩阵