73. 矩阵置零

1.题目

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

2.示例

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]
输入: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]]

3.答案

不能一边遍历数组,一边在原数组上将 0 元素所在行和所在列全部变为0。.所以需要额外空间来记录0元素所在的行或者列。

①O(mn)额外空间

使用额外的数组保存更新后的数组元素。

void setZeroes(vector<vector<int>>& matrix) {
     vector<vector<int> > res(matrix.begin(),matrix.end());
     for(int i=0;i<matrix.size();i++){
         for(int j=0;j<matrix[0].size();j++){
             if(matrix[i][j]==0){
                 for(int p=0;p<matrix[0].size();p++)  res[i][p]=0; //第i行
                 for(int p=0;p<matrix.size();p++) res[p][j]=0;  //第j列
             }
         }
     }

     matrix.assign(res.begin(),res.end());
    }

②O(m+n)额外空间

使用额外的两个一维数组数组集合保存0元素所在的行或列,然后进行更新。

void setZeroes(vector<vector<int>>& matrix) {
   unordered_set<int> row;  //出现0元素的行
    unordered_set<int> col;   //出现0元素的列

    for(int i=0;i<matrix.size();i++){
        for(int j=0;j<matrix[0].size();j++)
            if(matrix[i][j]==0) {
                row.insert(i);
                col.insert(j);
            }
        }

        for(int i:row){
            for(int j=0;j<matrix[0].size();j++)
            matrix[i][j]=0;
        }

      for(int i:col){
            for(int j=0;j<matrix.size();j++)
            matrix[j][i]=0;
        }
}

void setZeroes(vector<vector<int>>& matrix) {
        vector<int> row;  //记录需要清零的行数
        vector<int> col; //记录需要清零的列数

        for(int i=0;i<matrix.size();i++){
            for(int j=0;j<matrix[0].size();j++){
                if(matrix[i][j]==0){
                    row.push_back(i);  //此行需要清零
                    col.push_back(j);  //此列需要清零
                }
            }
        }

        for(int i:row) {
            for(int j=0;j<matrix[0].size();j++) matrix[i][j]=0;
        }

        for(int i:col){
            for(int j=0;j<matrix.size();j++) matrix[j][i]=0;
        }

    }

③O(1)空间

刚好可以利用第一行和第一列作为两个一维数组标记0所在行或列,此时需要额外的标记记录第0行和第0列是否需要置零。
记录第0行和第0列的情况之后,继续遍历剩下的元素,将需要清零的行数保存到数组第0列,列数保存到数组第0行。

    void setZeroes(vector<vector<int>>& matrix) {
        
        // 使用数组的第一行和第一列保存要清零的列数和行数
        
        //首先需要变量记录第0行和第0列是否需要清零
        int row=0,col=0;
        for(int i=0;i<matrix[0].size();i++) 
            if(matrix[0][i]==0) row=1;   //第0行需要清零

        for(int i=0;i<matrix.size();i++) 
            if(matrix[i][0]==0) col=1;  //第0列需要清零


        for(int i=1;i<matrix.size();i++){
            for(int j=1;j<matrix[0].size();j++){
                if(matrix[i][j]==0){
                   matrix[i][0]=0;  //第i行需要清零
                   matrix[0][j]=0;  //第j列需要清零
                }
            }
        }

    for(int i=1;i<matrix.size();i++){   //检查第1列有哪个位置标记为0
        if(matrix[i][0]==0) {   //第i行置零
        for(int j=1;j<matrix[0].size();j++){
            matrix[i][j]=0;
        }
        }
    }

    for(int j=1;j<matrix[0].size();j++){  //检查第1行有哪个位置标记为0
        if(matrix[0][j]==0){  //第j列清零
            for(int i=1;i<matrix.size();i++){
            matrix[i][j]=0;
        }
        }
    }

    if(row) {  //第0行置零
        for(int i=0;i<matrix[0].size();i++) matrix[0][i]=0;
    }
    if(col){  //第0列置零
        for(int i=0;i<matrix.size();i++) matrix[i][0]=0;
    }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值