2021-7-26 73. 矩阵置零(原地修改数组)

注:
第一行和第一列为标记,因此修改矩阵时要从第二行第二列开始改起,最后才改第一行和第一列。

题目:
给定一个 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

题解:
方法一:使用两个标记变量
思路和算法
我们可以用矩阵的第一行和第一列作为两个标记数组,以记录该行或者该列是否存在0。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 0。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含 0。

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

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

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int row=matrix.size();
        int col=matrix[0].size();
        bool rowflag=false;
        bool colflag=false;
        for(int j=0;j<col;j++){
            if(matrix[0][j]==0){
                rowflag=true;
                break;
            }
        }
        for(int i=0;i<row;i++){
            if(matrix[i][0]==0){
                colflag=true;
                break;
            }
        }
        for(int i=1;i<row;i++){
            for(int j=1;j<col;j++){
                if(matrix[i][j]==0){
                    matrix[i][0]=0;
                    matrix[0][j]=0;
                }
            }
        }
        for(int i=1;i<row;i++){
            for(int j=1;j<col;j++){
                if(matrix[i][0]==0||matrix[0][j]==0){
                    matrix[i][j]=0;
                }
            }
        }
        if(rowflag==true){
            for(int j=0;j<col;j++){
                matrix[0][j]=0;
            }
        }
        if(colflag==true){
            for(int i=0;i<row;i++){
                matrix[i][0]=0;
            }
        }
        return ;
    }
};

方法二:使用一个标记变量
思路和算法
我们可以对方法一进一步优化,只使用一个标记变量记录第一列是否原本存在 0。这样,matrix[0][0]即可以标记第一行是否出现 0。

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

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int row=matrix.size();
        int col=matrix[0].size();
        bool colflag=false;
        for(int i=0;i<row;i++){
            if(matrix[i][0]==0){
                colflag=true;
                break;
            }
        }
        for(int j=0;j<col;j++){
            if(matrix[0][j]==0){
                matrix[0][0]=0;
                break;
            }
        }
        for(int i=1;i<row;i++){
            for(int j=1;j<col;j++){
                if(matrix[i][j]==0){
                    matrix[i][0]=0;
                    matrix[0][j]=0;
                }
            }
        }
        for(int i=1;i<row;i++){
            for(int j=1;j<col;j++){
                if(matrix[i][0]==0||matrix[0][j]==0){
                    matrix[i][j]=0;
                }
            }
        }
        if(matrix[0][0]==0){
            for(int j=0;j<col;j++){
                matrix[0][j]=0;
            }
        }
        if(colflag==true){
            for(int i=0;i<row;i++){
                matrix[i][0]=0;
            }
        }
        return ;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值