力扣73矩阵置零

73. 矩阵置零 - 力扣(LeetCode)

给定一个 m x n 的矩阵,如果一个元素为 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
  • -231 <= matrix[i][j] <= 231 - 1

进阶:

  • 一个直观的解决方案是使用 O(_m__n_) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(_m_ + _n_) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗?

方法一:最暴力的解法(非原地)

直接遍历数组,遇到0就再分别遍历行和列。

问题:遇到0之后,将其所在行和列的所有元素都置0,后续遍历到"原本为1但被置0"的格子,会误判为该格子原本就是0,进而导致将该格子行列所在元素错误地置0

解决方法:使用一个flag数组记录matrix原本的模样,if条件中只需判断flag中该位置是否为0即可

代码:

java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        int[][] flag = new int[row][];
        for(int i=0;i<row;i++) {
            flag[i] = matrix[i].clone();
        }
        for(int i=0;i<row;i++) {
            for(int j=0;j<col;j++) {
                if(flag[i][j] == 0) {
                    for(int m=0;m<col;m++) {
                        matrix[i][m] = 0;
                    }
                    for(int n=0;n<row;n++) {
                        matrix[n][j] = 0;
                    }
                }
            }
        }
    }
}

因为时间问题,就没写Go/Python/C++版本了,后续的文章主要都是Java/Go/Python版本

时间复杂度:

  • 最好情况:矩阵全为1,O(mn)
  • 最坏情况:矩阵全为0,O(mn(m+n))
  • 其中m、n分别为矩阵的行数与列数

方法二:使用额外数组记录该行/列是否含0(非原地)

使用一个长为row的布尔数组 rowHasZero[] 记录第 i 行是否含0,如果含0,rowHasZero[i] = true

列同理

判断完行列是否含0后,再次遍历matrix,如果 rowHasZero/colHasZero 为true,就把该行/列的所有元素都置0

java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        boolean rowHasZero[] = new boolean[row];
        boolean colHasZero[] = new boolean[col];
        for(int i=0;i<row;i++) {
            for(int j=0;j<col;j++) {
                if(matrix[i][j] == 0) {
                    rowHasZero[i] = true;
                    colHasZero[j] = true;
                }
            }
        }

        for(int i=0;i<row;i++) {
            for(int j=0;j<col;j++) {
                if(rowHasZero[i] || colHasZero[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
}

方法三:用行头/列头代替两个HasZero数组(原地)

如果这一行有0,那么标记行头为0,后续置0时通过行头即可判断是否要将该行全部置0,列同理

问题:

考虑第一行全为1,第一列含0的矩阵,例如:

复制代码
1 1 1
1 1 1
0 1 1

行列判断完后,变为:

复制代码
0 1 1
1 1 1
0 1 1

此时开始置0,会误判为第一行有0,因为(0,0)是第一行和第一列的交点,所以这个位置为0无法判断究竟是行要置0还是列要置0,因此第一行和第一列需要用两个单独的布尔变量去判断是否含0,最后再分别处理

java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        //使用行头和列头记录是否含0
        boolean firstRowHasZero = false;
        boolean firstColHasZero = false;
        for(int x : matrix[0]) {
            if(x == 0) {
                firstRowHasZero = true;
                break;
            }
        }
        for(int i=0;i<row;i++) {
            if(matrix[i][0] == 0) {
                firstColHasZero = true;
                break;
            }
        }

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

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

        if(firstRowHasZero) {
            Arrays.fill(matrix[0],0);
        }
        if(firstColHasZero) {
            for(int[] r : matrix) {
                r[0] = 0;
            }
        }
    }
}

结语

本文含0量极高,那么以下cp中究竟谁是0呢?

千束 & 泷奈

伞哥 & 小肥宅

罗mio & 朱律叶

明日香 & 香织

彩叶 & 辉夜

小林 & 托尔

夏纪 & 优子

相关推荐
liang_jy9 小时前
文件管理(一)—— 初识文件管理
面试·操作系统
liang_jy10 小时前
文件管理(二)—— 文件结构
面试·操作系统
徐小夕10 小时前
花了一周,3亿tokens,我开源了一款 Word 文档智能审查平台,文稿自动质检+可视化分析,告别低效人工审核
前端·算法·github
Ai拆代码的曹操10 小时前
Spring 事务 REQUIRES_NEW 嵌套调用:连接池翻倍的秘密
java·后端·spring
动恰客流统计11 小时前
ReID边缘计算视觉统计:餐饮店客流增长的数字化破局路径
java·大数据·运维·人工智能
可编程芯片开发11 小时前
UPFC统一潮流控制器的simulink建模与仿真
算法
Ivanqhz12 小时前
Rust &‘static str浅析
java·前端·javascript·rust
小小仙子12 小时前
矢量网络分析仪如何测试S参数的?
人工智能·算法·机器学习
中微极客14 小时前
降维算法75倍加速:从PCA到稀疏字典学习的工程实践
人工智能·学习·算法