zoukankan      html  css  js  c++  java
  • LeetCode (73): Set Matrix Zeroes

    链接: https://leetcode.com/problems/set-matrix-zeroes/

    【描述】

    Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.

    【中文描述】

    给一个二维数组,如果哪一个位置为0,那么该行该列全部置为0。

    ————————————————————————————————————————————————————————————

    【初始思路】

    首先想到的思路,最简单的,二层循环,哪一行遇到0, 把行号记录到行map里。 哪一列遇到,把列好记录到列map里。

    然后,对每个map迭代,把对应行和列置为0就行。

    不用分析了,直接上代码。

    【Show me the Code!!!】

    setZeroes

    很明显,使用了额外空间,而且空间复杂度为O(m+n), 因为行map大小最坏情况==m, 列map大小最坏情况==n。

    【Follow-up Question】

    能否不用额外空间做,用常数空间?

    这个时候应该有一个意识,遇到数组、矩阵的数据,还要求常数空间的,尽量尝试在数组和矩阵中保存中间结果来实现。

    本题也不例外!

    怎么保存?

    可以从题目要求着手分析。不管在哪个位置遇到了0, 该行该列的其他数字,最终都没有任何意义,因为最终都要被置为0。那么我们可否在该行该列找一个位置用来做个mark呢?

    那么,最简单的mark位置,就是第一行第一列嘛。 用第一行来保存各个列的mark,用第一列来保存各个行的mark。最终,分别看第一行和第一列的mark把该行该列置为0不就完了么?!

    想起来是很清晰简单的,但是实现了一下,试了两个用例就不行了,我们来看看下面的例子。

                                   

    按照上面算法, 在执行完行列mark后,矩阵变为:

                                     

    那么,按照上面的第一行第一列置位的算法,第一行全部置为0(上方红色箭头), 第一列全部置为0(左边红色箭头),矩阵变为下面:

                                     

    这显然是错误的,因为第一行除了第一个位置外,其他位置不应该置为0.

    问题出在哪里?

    应该能看到,问题出在了第一行第一列。因为我们用第一行存储各列的置位情况,用第一列存储各行的置位情况。那么第一行第一列岂不身兼两职?

    所以,我考虑引入一个int extra位,单独用来做第一行的置位,而让第一行第一列位置只作第一列的置位情况,这样就把职责区分开了,看下图

                       

    当第一行中有零的时候,extra置为0,作为第一行的mark, 而[0][0]位置作为第一列的mark。那么在mark循环执行完后,矩阵变为上面的样子。

    到了这里接下来怎么做就一目了然了, 各行各列还是按照mark位是否为0来给各行各列置位。

    我们来看下面例子:

                                 

    显然, 最终变化应该是第一行和最后一列变为0,其他都保持不变, 我们按照上面的改进算法来走走看:

    当走完所有mark流程后,矩阵变为:

                           

    这一步没问题, 接下来,我们对各行各列置位, 首先因为extra负责的是第一行的置位mark, 此时extra==0, 所以第一行全部置位0:

                            

    接下来,第二行置位,第二行第一列不是0, 所以本行无需置位。

    然后,根据第一行各列对矩阵各个列进行置位,问题来了,根据上面的结果, 这个时候,置位将变为:

                            

    这什么情况?!?

    显然,原因出在,第一行根据extra置位的时候,我们错误地把[0][0]位也置为0了, 因为[0][0]位其实指示的是第一列的mark,所以[0][0]位不能动!

    OK,按行置位改进一下:对第一行第一列不动。其他行算法不变。

    这个时候,再根据第一行各个列的情况,对各列置位。

    最最后, 一定不能忘记,[0][0]位置我们在按行置位的时候是跳过的,而按列置位的时候,结果也并不会影响这一位的情况。所以在程序的最后,一定要看看[0][0]位是否需要置位为0,根据什么看呢?对了!extra位!

    【Show me the Code!!!】   

     1 public static void setZeroesConstanceSpace(int[][] matrix) {
     2         if (matrix == null) return;
     3         int extra = Integer.MAX_VALUE;
     4         for (int i = 0; i < matrix.length; i++) {
     5             for (int j = 0; j < matrix[0].length; j++) {
     6                 if (matrix[i][j] == 0) {
     7                     //借助matrix自身记录i和j
     8                     if (i == 0) {
     9                         //第一行记录到一个附加位上
    10                         extra = 0;
    11                     } else {
    12                         matrix[i][0] = 0;
    13                     }
    14                     matrix[0][j] = 0;
    15                 }
    16             }
    17         }
    18         //遍历第一行,从第2列到最后一列, 确定哪些列需要置0
    19         for (int i = 1; i < matrix[0].length; i++) {
    20             if (matrix[0][i] == 0) {
    21                 for (int j = 0; j < matrix.length; j++) {
    22                     matrix[j][i] = 0;
    23                 }
    24             }
    25         }
    26 
    27         //遍历第一列第1行到最后一行, 确定都有哪些行需要置0
    28         //第一行第一列先不做变动
    29         for (int i = 0; i < matrix.length; i++) {
    30             if (i == 0) {
    31                 if (extra == 0) {
    32                     for (int j = 1; j < matrix[0].length; j++) {
    33                         matrix[0][j] = 0;
    34                     }
    35                 }
    36             } else {
    37                 if (matrix[i][0] == 0) {
    38                     for (int j = 0; j < matrix[0].length; j++) {
    39                         matrix[i][j] = 0;
    40                     }
    41                 }
    42             }
    43         }
    44 
    45         //看看matrix[0][0]是否需要把第一列置0
    46         if (matrix[0][0] == 0) {
    47             for (int i = 0; i < matrix.length; i++) {
    48                 matrix[i][0] = 0;
    49             }
    50         }
    51         if (extra == 0) {
    52             matrix[0][0] = 0;
    53         }
    54     }
    setZeroesConstanceSpace
  • 相关阅读:
    闭包装饰器与递归
    内置函数学习
    可迭代对象 迭代器 生成器 推导式 匿名函数
    函数基础
    python文件操作
    深浅copy与小数据池
    python数据类型
    python基础语法
    view视图函数的书写 请求与响应相关
    LeetCode OJ:Rotate Image(旋转图片)
  • 原文地址:https://www.cnblogs.com/lupx/p/leetcode-73.html
Copyright © 2011-2022 走看看