矩阵置零[中等]

优质博文:IT-BLOG-CN

一、题目

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

示例 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]]

m == matrix.length
n == matrix[0].length
1 <= m, n <= 200
-231 <= matrix[i][j] <= 231 - 1

二、代码

【1】使用标记数组: 我们可以用两个标记数组分别记录每一行和每一列是否有零出现。具体地,我们首先遍历该数组一次,如果某个元素为0,那么就将该元素所在的行和列所对应标记数组的位置置为true。最后我们再次遍历该数组,用标记数组更新原数组即可。

java 复制代码
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;
                }
            }
        }
    }
}

时间复杂度: O(mn),其中m是矩阵的行数,n是矩阵的列数。我们至多只需要遍历该矩阵两次。
空间复杂度: O(m+n),其中m是矩阵的行数,n是矩阵的列数。我们需要分别记录每一行或每一列是否有零出现。

【2】使用两个标记变量: 我们可以用矩阵的第一行和第一列代替方法一中的两个标记数组,以达到O(1)的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 000。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含0。在实际代码中,我们首先预处理出两个标记变量,接着使用其他行与列去处理第一行与第一列,然后反过来使用第一行与第一列去更新其他行与列,最后使用两个标记变量更新第一行与第一列即可。

java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        boolean flagCol0 = false, flagRow0 = false;
        for (int i = 0; i < m; i++) {
            if (matrix[i][0] == 0) {
                flagCol0 = true;
            }
        }
        for (int j = 0; j < n; j++) {
            if (matrix[0][j] == 0) {
                flagRow0 = true;
            }
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][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 (flagCol0) {
            for (int i = 0; i < m; i++) {
                matrix[i][0] = 0;
            }
        }
        if (flagRow0) {
            for (int j = 0; j < n; j++) {
                matrix[0][j] = 0;
            }
        }
    }
}

时间复杂度: O(mn),其中m是矩阵的行数,n是矩阵的列数。我们至多只需要遍历该矩阵两次。
空间复杂度: O(1)。我们只需要常数空间存储若干变量。

使用一个标记变量: 我们可以对方法二进一步优化,只使用一个标记变量记录第一列是否原本存在0。这样,第一列的第一个元素即可以标记第一行是否出现0。但为了防止每一列的第一个元素被提前更新,我们需要从最后一行开始,倒序地处理矩阵元素。

java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        boolean flagCol0 = false;
        for (int i = 0; i < m; i++) {
            if (matrix[i][0] == 0) {
                flagCol0 = true;
            }
            for (int j = 1; j < n; j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = matrix[0][j] = 0;
                }
            }
        }
        for (int i = m - 1; i >= 0; i--) {
            for (int j = 1; j < n; j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
            if (flagCol0) {
                matrix[i][0] = 0;
            }
        }
    }
}

时间复杂度: O(mn),其中m是矩阵的行数,n是矩阵的列数。我们至多只需要遍历该矩阵两次。
空间复杂度: O(1)。我们只需要常数空间存储若干变量。

相关推荐
JustNow_Man2 分钟前
【Harness】本地文本向量化搜索解决方案--qmd
git·python·算法
小林ixn2 分钟前
用 FastAPI + SQLAlchemy 从零手搓一个博客系统:一套能落地、能讲清楚的 RESTful 后端
后端·python·fastapi
Wang's Blog9 分钟前
Java 项目实战: 交友项目 - 查询推荐动态
java·开发语言·交友
不识君10 分钟前
esl-client 2.0.0 发布:Java 项目接入 FreeSWITCH,从引入到使用
spring boot·后端·开源
jaysee-sjc16 分钟前
【苍穹外卖】Day10:定时任务与 WebSocket 实时提醒实战
java·开发语言·javascript·数据库·vue.js·websocket·网络协议
敲代码的苦1318 分钟前
头歌 数据结构—消防资源调度
数据结构·算法
ysu_031418 分钟前
【C++ 进阶之路】(二)从内联函数到类与对象:深挖内存对齐、this 指针与三大默认成员函数
开发语言·数据结构·c++·笔记·面向对象·this
独隅19 分钟前
Claude 高效应用实战指南
android·java·开发语言·claude·claude code
布莱克60524 分钟前
C++ 中 set 与 map 的区别详解
开发语言·c++·算法·哈希
WJ.Polar25 分钟前
异常、泛型、集合、Stream流
java·数据结构