本文介绍: 在实际代码中,我们首先预处理两个标记变量,接着使用其他行与列去处理第一行第一列然后反过来使用第一行与第一列去更新其他行与列,最后使用两个标记变量更新第一行与第一列即可。但这样会导致原数组第一行和第一列被修改,无法记录它们是否原本包含 000。但为了防止每一列的第一个元素被提前更新我们需要最后一行开始,倒序处理矩阵元素我们可以矩阵第一行和第一列代替方法一中的两个标记数组,以达到。最后我们再次遍历该数组,用标记数组更新数组即可我们至多只需要遍历该矩阵两次。我们至多只需要遍历该矩阵两次

优质博文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 &lt;= matrix[i][j] <= 231 - 1

二、代码

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

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。在实际代码中,我们首先预处理出两个标记变量,接着使用其他行与列去处理一行与第一列,然后反过来使用第一行与第一列去更新其他行与列,最后使用两个标记变量更新第一行与第一列即可

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。但为了防止每一列的第一个元素被提前更新,我们需要从最后一行开始,倒序地处理矩阵元素。

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

原文地址:https://blog.csdn.net/zhengzhaoyang122/article/details/134656346

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_39362.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注