LeetCode热题100——73.矩阵置零(题目+题解+答案)

题目:

给定一个 mxn 的矩阵,如果一个元素为 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

  • -2^31 <= matrix[i][j] <= 2^31 - 1

题解:

法一:空间复杂度O(m+n)

思路:

遍历一次矩阵,记录下所有0元素所在的行号和列号,然后第二次遍历时,只要当前位置的行号或列号被标记过,就把该位置置为0。

标记信息可以用两个布尔数组实现:一个长度为 m 的 row 数组,rowi = true 表示第 i 行需要清零;另一个长度为 n 的 col 数组,colj = true 表示第 j 列需要清零。

代码:
cpp 复制代码
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m=matrix.size();
        int n=matrix[0].size();
        vector <int> row(m),col(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]==true||col[j]==true) matrix[i][j]=0;
            }
        }
    }
};

法二:空间复杂度O(1)

思路:

借用矩阵第一行和第一列作为标记数组。

详细步骤:
步骤 1:检查第一行和第一列是否原本包含0
  • 遍历就第一行,如果有元素为 0,则设置 firstRowHasZero = true
  • 遍历第一列,如果有元素为 0,则设置 firstColHasZero = true
步骤 2:用第一行和第一列作为标记数组

遍历矩阵的内部区域(即下标从 1 到 m-1 的行,1 到 n-1 的列):

  • 如果 matrixij == 0,则:
    • 将 matrixi0 设为 0 ------ 标记第 i 行需要清零
    • 将 matrix0j 设为 0 ------ 标记第 j 列需要清零
步骤 3:根据标记清零内部区域

再次遍历内部区域(即下标从 1 到 m-1 的行,1 到 n-1 的列):

如果 matrixi0 == 0 或 matrix0j == 0,则把 matrixij 设为 0。

步骤 4:处理第一行和第一列
  • 如果 firstRowHasZero 为true,则将第一行的所有元素设为 0。
  • 如果 firstColHasZero 为true,则将第一列的所有元素设为 0。
代码:
cpp 复制代码
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
    int m=matrix.size();
    int n=matrix[0].size();
    bool firstRowHasZero=false;
    bool firstColHasZero=false;
    //步骤1:检查第一行和第一列是否原本包含0
    for(int j=0;j<n;j++){
        if(matrix[0][j]==0) firstRowHasZero=true;
    }
    for(int i=0;i<m;i++){
        if(matrix[i][0]==0) firstColHasZero=true;
    }
    //步骤2:用第一行和第一列作为标记数组
    for(int i=1;i<m;i++){
        for(int j=1;j<n;j++){
            if(matrix[i][j]==0){
                matrix[i][0]=0;
                matrix[0][j]=0;
            } 
        }
    }
    //步骤3:根据标记清零内部区域
    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;
        }
    }
    //步骤4:处理第一行和第一列
    if(firstColHasZero){
        for(int i=0;i<m;i++) matrix[i][0]=0;
    }
    if(firstRowHasZero){
        for(int j=0;j<n;j++) matrix[0][j]=0;
    }
    }
};
相关推荐
木木子224 小时前
# 密码强度检测深度解析:正则表达式实时分析、多维度评分算法与可视化反馈
mysql·算法·华为·正则表达式·harmonyos
Sw1zzle7 小时前
算法入门(四):二叉树 - 递归遍历三件套
算法·leetcode
万法若空8 小时前
【算法-查找】查找算法
java·数据结构·算法
海石8 小时前
子树怎么找?树的3种遍历方式来帮忙!
算法·leetcode
海石8 小时前
难度分 1588:思路 + 技巧 = AC
算法·leetcode
殳翰8 小时前
下服务器端开发流程及相关工具介绍(C++)
开发语言·c++
青瓦梦滋9 小时前
协议定制/序列化-反序列化(Linux视角)
linux·服务器·网络·c++
珠海西格电力11 小时前
云边端协同架构:零碳园区管理系统的技术底座
大数据·运维·人工智能·算法·架构·能源
山登绝顶我为峰 3(^v^)312 小时前
C/C++ 交叉编译方法
java·c语言·c++
还有多久拿退休金13 小时前
让飞书知识库跟着 commit 自己长:一套自动化知识库的真实实现
前端·算法·架构