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;
    }
    }
};
相关推荐
JieE2124 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack2011 小时前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树13 小时前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2121 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2121 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术1 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦1 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
clint4562 天前
C++进阶(1)——前景提要
c++
用户497863050732 天前
(一)小红的数组操作
算法·编程语言