LeetCode73. 矩阵置零

Posted machine_gun_lin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode73. 矩阵置零相关的知识,希望对你有一定的参考价值。

解法一(使用O(mn)空间)

可以开一个额外的二维数组,记录每个位置的元素是否已被访问过。

然后我们遍历原来的二维数组,只要没被访问过且元素为0,那么就将该元素所在的行和列的元素值置为0,
并且将这一行的所有元素都设置为已经访问过,以免之后的遍历碰到被置为0的元素也将那一行那一列的元素置为0.

这里要注意,对于一个为0且未被访问的元素所在的行和列的元素置0的时候,要跳过本来就为0的元素,因为可能之后的遍历
到了其他的本来就为0的元素,由于置了那个元素的状态为访问过,就会跳过这个元素,导致没有将那个元素所在的行和列所在的
元素置0.

代码如下:

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int rows = matrix.size(), cols = matrix[0].size();      
        vector<vector<bool>> visited(rows, vector<bool>(cols));      //记录每个元素是否已被访问过
        for(int i = 0; i < rows; ++i) {
            for(int j = 0; j < cols; ++j) {
                if(visited[i][j] == false && matrix[i][j] == 0) {      //只有当元素为0且未被访问过时,才修改这一行这一列的元素
                    for(int k = 0; k < rows; ++k) {
                        if(matrix[k][j] != 0) {                  //这个if判断不能少,目的是为了防止将这一列本来就为0的元素置为已经访问过,导致无法将那个本就为0的元素所在的行和列的元素置0, 下面的if语句同理
                            matrix[k][j] = 0;
                            visited[k][j] = true;
                        }
                    }
                    for(int k = 0; k < cols; ++k) {
                        if(matrix[i][k] != 0) {
                            matrix[i][k] = 0;
                            visited[i][k] = true;
                        }
                    }
                }
            }
        }
    }
};

解法二(使用O(m + n)空间)

给每一个元素都设置一个访问状态需要开二维数组,有点麻烦。

由于我们只需要把0所在的行和列的元素置为0,所以我们可以这样:遍历一遍数组,如果某个元素为0,
那么我们记录一下这个元素的行号和列号。

最后把所有我们记录过的行和列的元素全部置为0即可。

使用这种方法需要开一个O(n)的数组记录每一行是否有0元素,还要开一个O(m)数组记录每一列是否有0元素。
因此空间开销是O(m + n)。

代码如下:

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int rows = matrix.size(), cols = matrix[0].size();
        vector<int> rowHasZero(rows), colHasZero(cols);      //两个数组分别记录每一行和每一列是否有0元素
        for(int i = 0; i < rows; ++i) {
            for(int j = 0; j < cols; ++j) {
                if(matrix[i][j] == 0) {                  //如果某个元素为0,记录下它的行号和列号
                    rowHasZero[i] = 1;
                    colHasZero[j] = 1;
                }
            }
        }
        for(int i = 0; i < rows; ++i) {      
            if(rowHasZero[i] == 1) {                     //将存在0元素的行的所有元素都置0
                for(int j = 0; j < cols; ++j) {
                    matrix[i][j] = 0;
                }
            }
        }
        for(int j = 0; j < cols; ++j) {                  //将存在0元素的列的所有元素都置0
            if(colHasZero[j] == 1) {
                for(int i = 0; i < rows; ++i) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
};

解法三 (使用常数空间)

由于要将0元素所在的行和列所在的所有元素都置为0,我们就需要记录哪些行哪些列含有0元素,但是又不能开数组记录,那怎么办呢?

可以考虑直接用原数组记录,比如解法二里开了一个列大小的数组记录每一行是否有0,又开了一个行大小的数组记录每一列是否有0.

我们可以直接在第0行和第0列记录! 比如,如果martix[i][j]为0,那么我们就让martix[i][0]为0,表示第i行含有元素0,之后需要将该行所有元素都改为0.
再让martix[0][j]为0,表示第j列含有元素0,之后需要讲该列所有元素都改为0.

这样我们就不需要额外开数组了,但是又有个问题,这样修改了原来的第0行和第0列的元素,咋办?

问题不大,只能开常数空间,不代表不能开空间,我们额外用两个变量记录第0行和第0列是否有0,如果有,在最后就将第0行(列)的所有元素改为0,
如果没有,那么如果第0行或第0列的元素所在的行(列)没有0,那么他们还是原来的值(没有被修改),如果有,那说明(对第0行/列元素的修改)正好改对了呀,
反正他们最后本来就是0! 这样就解决了空间的问题,使用常数空间就可以将矩阵置0.

代码如下:

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int rows = matrix.size(), cols = matrix[0].size();
        int firstRowHasZero = 0, firstColHasZero = 0;      //判断第0行和第0列是否有元素0
        for(int i = 0; i < cols; ++i) {
            if(matrix[0][i] == 0) {                        //如果第0行有元素0,修改firstRowHasZero,在程序最后将第0行所有元素都改为0
                firstRowHasZero = 1;
                break;
            }
        }
        for(int i = 0; i < rows; ++i) {
            if(matrix[i][0] == 0) {                        //如果第0列有元素0,修改firstColHasZero,在程序最后将第0列所有元素都改为0
                firstColHasZero = 1;
                break;
            }
        }
        for(int i = 1; i < rows; ++i) {               
            for(int j = 0; j < cols; ++j) {
                if(matrix[i][j] == 0) {
                    matrix[i][0] = 0;                 //如果某元素为0,修改martix[i][0]为0,表示第i行的元素最后需要全部改为0
                    break;
                }
            }
        }
        for(int j = 1; j < cols; ++j) {
            for(int i = 0; i < rows; ++i) {
                if(matrix[i][j] == 0) {
                    matrix[0][j] = 0;                 //如果某元素为0,修改martix[i][0]为0,表示第j列的元素最后需要全部改为0
                    break;
                }
            }
        }
        for(int i = 1; i < rows; ++i) {
            if(matrix[i][0] == 0) {                  //第i行有0元素,把第i行所有元素都改为0
                for(int j = 1; j < cols; ++j) {
                    matrix[i][j] = 0;
                }
            }
        }
        for(int j = 1; j < cols; ++j) {
            if(matrix[0][j] == 0) {                  //第j列有0元素,把第j列所有元素都改为0
                for(int i = 1; i < rows; ++i) {
                    matrix[i][j] = 0;
                }
            }
        }
        if(firstRowHasZero) {
            for(int j = 0; j < cols; ++j) {          //第0行有0元素,把第0行所有元素都改为0
                matrix[0][j] = 0;
            }
        }
        if(firstColHasZero) {
            for(int i = 0; i < rows; ++i) {          //第0列有0元素,把第0列所有元素都改为0
                matrix[i][0] = 0;
            }
        }
    }
};

以上是关于LeetCode73. 矩阵置零的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode刷题Python73. 矩阵置零

leetcode73矩阵置零

leetcode-73 矩阵置零

Python描述 LeetCode 73. 矩阵置零

Python描述 LeetCode 73. 矩阵置零

Python描述 LeetCode 73. 矩阵置零