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 数组,row[i] = true 表示第 i 行需要清零;另一个长度为 n 的 col 数组,col[j] = 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 的列):

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

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

如果 matrix[i][0] == 0 或 matrix[0][j] == 0,则把 matrix[i][j] 设为 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;
    }
    }
};
相关推荐
脱氧核糖核酸__1 小时前
LeetCode热题100——41.缺失的第一个正数(题解+答案+要点)
数据结构·c++·算法·leetcode·哈希算法
Mr_Xuhhh1 小时前
深入理解单链表的递归反转:从原理到实现
算法·leetcode·职场和发展
智者知已应修善业1 小时前
【51单片机数码管+蜂鸣器的使用】2023-6-14
c++·经验分享·笔记·算法·51单片机
艾莉丝努力练剑2 小时前
【Linux线程】Linux系统多线程(七):<线程同步与互斥>线程同步(下)
java·linux·运维·服务器·c++·学习·操作系统
迷途之人不知返2 小时前
算法类型:双指针类型
算法
c++逐梦人2 小时前
C++ RAII流式日志库实现
开发语言·c++
吴可可1232 小时前
三点绘圆弧的几何实现
算法
t***5442 小时前
还有哪些设计模式适合现代C++
开发语言·c++·设计模式
Wave8452 小时前
C++ 面向对象基础:类、访问权限,构造函数,析构函数
开发语言·c++