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;
    }
    }
};
相关推荐
我变成萤火虫4 小时前
河南萌新联赛2026第(四)场:南阳理工学院
数据结构·c++·算法·贪心算法·stl·动态规划
To_OC7 小时前
LC 239 滑动窗口最大值:从暴力超时到单调队列一遍过
javascript·算法·leetcode
.道阻且长.8 小时前
9.LeetCode算法习题讲解--滑动窗口--无重复字符的最长字串
算法·leetcode·职场和发展·哈希算法
余额瞒着我当琳8 小时前
C++--深拷贝三件套 + swap + 写时拷贝 + vector 扩容 + reserve
java·开发语言·c++
ltl9 小时前
HNSW:图索引如何击败树索引
算法
ShineWinsu10 小时前
对于C++:布隆过滤器(bloomfilter)的详细解析
c++·面试·位图·位运算·布隆过滤器·海量数据·比特位
曹牧10 小时前
C#:数字的定义和表示方式
算法·c#
Nil20811 小时前
leetcode 138随机链表的复制
算法·leetcode·链表
疯狂打码的少年12 小时前
【数据结构】图的遍历:深度优先搜索(DFS)
数据结构·笔记·算法·深度优先