Leetcode 73:矩阵置零(最详细的解法!!!)

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法**。**

示例 1:

输入: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
输出: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

输入: 
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
输出: 
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

进阶:

  • 一个直接的解决方案是使用 O(m**n) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个常数空间的解决方案吗?

解题思路

一个最简答的思路就是通过遍历矩阵的每一个元素,判断这个元素是不是0,如果是的话那么将对应的行和列的元素置为零,但是这种有一个陷阱,因为一旦置为零,那么我们对于没有遍历到的元素就会存在这样的风险:原先不是0,但是因为之前有数将其置为0了,我们遍历到这个原本是非0数的时候就不要将其行和列置为零了。为例解决这个问题,我们需要重新开辟一个矩阵大小的空间用来存储最后的0

from copy import deepcopy
class Solution:
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        if not matrix:
            return
        r, c = len(matrix), len(matrix[0])
        mat = deepcopy(matrix)

        for i in range(r):
            for j in range(c):
                if mat[i][j] == 0:
                    for m in range(r):
                        matrix[m][j] = 0
                    for n in range(c):
                        matrix[i][n] = 0

注意这里要使用deepcopy,因为是两层的list结构。

有没有更好的做法呢?就像进阶中提到的,我们是不是有空间复杂度更小的做法。我们可以这样考虑,例如

对于第一行和第一列元素我们单独考虑。我们首先开始遍历除第一行第一列外的所有元素,当我们碰到0,也就是2,2这个点,所以我们将之前的同一行同一列的第一行和第一列置为0

接着我们根据第一行和第一列的0和非0将矩阵的(除了第一行第一列)行和列全置为0

我们接着要考虑第一行第一列的问题,如果第一行第一列一开始就有0的话((0,0)(2,0)),我们将对应行列(第一行第一列)置为0即可。

我们通过这个算法,就可以使用O(1)的空间复杂度解决这个问题。

class Solution:
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        if not matrix:
            return
        r, c, flagr, flagc = len(matrix), len(matrix[0]), False, False
        for i in range(r):
            if matrix[i][0] == 0:
                flagr = True
                
        for j in range(c):
            if matrix[0][j] == 0:
                flagc = True
                    
        for i in range(1, r):
            for j in range(1, c):
                if matrix[i][j] == 0:
                    matrix[0][j] = 0
                    matrix[i][0] = 0

        for i in range(1, r):
            for j in range(1, c):
                if not matrix[i][0] or not matrix[0][j]:
                    matrix[i][j] = 0

        if flagc:
            for j in range(c):
                matrix[0][j] = 0

        if flagr:
            for i in range(r):
                matrix[i][0] = 0

一种更加简洁的写法

class Solution:
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        if not matrix:
            return
        
        r, c, flag = len(matrix), len(matrix[0]), False               
        for i in range(r):
            if matrix[i][0] == 0:
                flag = True
            for j in range(1, c):
                if matrix[i][j] == 0:
                    matrix[0][j] = 0
                    matrix[i][0] = 0

        for i in range(r-1, -1, -1):
            for j in range(c-1, 0, -1):
                if not matrix[i][0] or not matrix[0][j]:
                    matrix[i][j] = 0
            if flag:
                matrix[i][0] = 0

基本思想同上,我们只需考虑第一列,然后遍历的过程中采用自底向上即可。

reference:

https://leetcode.com/problems/set-matrix-zeroes/solution/

https://leetcode.com/problems/set-matrix-zeroes/discuss/26014/Any-shorter-O(1)-space-solution

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值