矩阵置零[中等]

优质博文: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)。我们只需要常数空间存储若干变量。

相关推荐
语落心生7 分钟前
数控技术:数控系统刀补功能的软件实现及其仿真
后端
柯南二号9 分钟前
【Java后端】MyBatis-Plus 原理解析
java·开发语言·mybatis
又是努力搬砖的一年18 分钟前
SpringBoot中,接口加解密
java·spring boot·后端
:-)21 分钟前
idea配置maven国内镜像
java·ide·maven·intellij-idea
一只鱼^_23 分钟前
牛客周赛 Round 105
数据结构·c++·算法·均值算法·逻辑回归·动态规划·启发式算法
是阿建吖!24 分钟前
【动态规划】斐波那契数列模型
算法·动态规划
0wioiw028 分钟前
Python基础(Flask①)
后端·python·flask
啊阿狸不会拉杆1 小时前
《算法导论》第 27 章 - 多线程算法
java·jvm·c++·算法·图论
用户802973565411 小时前
【水平:编写简单的SpringCloud】用一篇文章精通SpringCloud-1
java
风象南1 小时前
SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
spring boot·后端