leetcode 01.08零矩阵

题目描述

若arr[i][j] == 0,则使得i行和j行所有单元格为0
零矩阵

分析

直接记录0元素的行和列。
时间复杂度O(m*n),必须遍历每个单元格。

sol0

开记录数组,O(m + n)空间复杂度。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int row = 0;
        int col = 0;

        row = matrix.size();
        if (row)
            col = matrix[0].size();
        
        set<int> c_set;
        set<int> r_set;
//记录i,j行是否有零
        for(int i = 0;i < row;i++){
            for(int j = 0;j < col;j++){
                if ( 0 == matrix[i][j]){
                    c_set.insert(j);
                    r_set.insert(i);
                }
            }
        }


//根据数组再写回到表格中去
        for(int i = 0;i < row;i++){
            for(int j = 0;j < col;j++){
                if ( c_set.end() != c_set.find(j) ||r_set.end() != r_set.find(i))
                    matrix[i][j] = 0;
            }
        }

    }
};

sol1

直接利用第一行和第一列记录。
用第一行的第2到第col列记录第2到第col列是否有0;
即用matrix[0][1]代表第2列是否有0,若matrix[0][1]为则表示第2列有0

同理,用第一列的第2到第row格子表示第2行到row行是否有0。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int row = 0;
        int col = 0;

        row = matrix.size();
        if (row)
            col = matrix[0].size();
        
        int row0_have0 = 0; 
        int col0_have0 = 0;

//检查第一行和第一列的情况
        for(int i = 0;i < col || i < row;i++){
            if(i < col &&!matrix[0][i])
                row0_have0 = 1;
            if(i < row &&!matrix[i][0])
                col0_have0 = 1;
        }
        
        for (int i = 1;i < row;i++){
            for (int j = 1;j < col;j++){
                if (!matrix[i][j]){
                    matrix[0][j] = matrix[i][0] = 0;
                }
            }
        }

        for(int i = 1;i < row;i++)
            for(int j = 1;j < col;j++)
                if (!matrix[0][j]  || !matrix[i][0])
                    matrix[i][j] = 0;

        if(row0_have0)
            for(int j = 0;j < col;j++)
                matrix[0][j] = 0;
        
        if(col0_have0)
            for(int i = 0;i < row;i++)
                matrix[i][0] = 0;

    }
};

sol2

在sol1的基础上,我们可以再把matrix[0][0]利用上。
用这个单元格子表示第一列是否有0或者第一行是否有0。
但是需要特别注意的是,需要倒序。
如第一行表示列状态时,从第二行的末尾开始设置。否则的话表示状态的第1列会被结果覆盖。

1. matrix[0][0]表示第一行有无0

这个时候,我们需要先检查第一列有无0。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int row = 0;
        int col = 0;

        row = matrix.size();
        if (row)
            col = matrix[0].size();
        
        int row0_have0 = 0; 

        for(int i = 0;i < col ;i++){
            if (!matrix[0][i])
                row0_have0 = 1;
        }
        
        for (int i = 1;i < row;i++){
            for (int j = 0;j < col;j++){
                if (!matrix[i][j]){
                    matrix[0][j] = matrix[i][0] = 0;
                }
            }
        }

        for(int i = 1;i < row;i++)
            for(int j = col - 1;~j;j--)
                if (!matrix[0][j]  || !matrix[i][0]){
                    matrix[i][j] = 0;
                }

        if(row0_have0){
            for(int j = 0;j < col;j++)
                matrix[0][j] = 0;
        }
       
    }
};

2. matrix[0][0]表示第一列有无0

这个时候,我们需要先检查第一行有无0。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int row = 0;
        int col = 0;

        row = matrix.size();
        if (row)
            col = matrix[0].size();
        
        int col0_have0 = 0; 

        for(int i = 0;i < row ;i++){
            if (!matrix[i][0])
                col0_have0 = 1;
        }
        
        for (int i = 0;i < row;i++){
            for (int j = 1;j < col;j++){
                if (!matrix[i][j]){
                    matrix[i][0] = matrix[0][j] = 0;
                }
            }
        }

        for (int i = row - 1; ~i; --i){
            for(int j = 1;j < col;++j){
                if (!matrix[i][0] || !matrix[0][j])
                    matrix[i][j] = 0;
            }
        }

        if (col0_have0)
            for(int i = 0;i < row;i++)
                matrix[i][0] = 0;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值