LeetCode :零矩阵

1. 题目

编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。
 

2.示例

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

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

 

3. 解题思路

3.1 方法一:使用两个标记数组

  • 第一次遍历:用两个标记数组row、col记录零出现的位置
  • 第二次遍历:根据两个标记数组更新数组

3.2 方法二:使用两个标记变量

  • 使用两个标记变量分别标记matrix的第一行和第一列是否有零出现
  • 将matrix的第一行和第一列作为方法一中的两个标记数组
  • 执行方法一中的两次遍历
    【从1开始遍历行,从1开始遍历列】

3.3 方法三:使用一个标记变量

在方法二中, m a t r i x [ 0 ] [ 0 ] matrix[0][0] matrix[0][0]元素并没有作为标记数组使用

  • 只使用一个标记变量记录第一列是否原本存在 0
  • 第一列的第一个元素即可以标记第一行是否出现 0
    【此时, m a t r i x [ 0 ] [ 0 ] matrix[0][0] matrix[0][0]元素作为标记数组使用】
  • 继续将matrix的第一行和第一列作为方法一中的两个标记数组
  • 执行方法一中的两次遍历
    【从0开始遍历行,从1开始遍历列】
  • 但为了防止每一列的第一个元素被提前更新,我们需要从最后一行开始,倒序地处理矩阵元素。
    【因为此时第一行元素是作为标记数组在使用】

 

4. 提交代码

4.1 方法一:使用标记数组

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        m, n = len(matrix), len(matrix[0])
        row, col = [False] * m, [False] * n

        # 第一次遍历记录0的位置
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0:
                    row[i] = col[j] = True
        
        # 第二次遍历根据0的位置更新matrix
        for i in range(m):
            for j in range(n):
                if row[i] or col[j]: # 此处更新matrix的方式稍微留意
                    matrix[i][j] = 0


4.2 方法二:使用两个标记变量

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        m, n = len(matrix), len(matrix[0])

        # 两个标记变量记录matrix第一行和第一列是否有出现0
        flag_row0 = any(matrix[0][i] == 0 for i in range(n)) 
        flag_col0 = any(matrix[j][0] == 0 for j in range(m))

        # 第一次遍历:用matrix的第一行和第一列记录sub_matrix零出现的位置
        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[i][0] = matrix[0][j] = 0

        # 第二次遍历:根据得到的标记数组更新sub_matrix
        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0

        # 根据flag_row0更新第一行
        if flag_row0:
            for j in range(n):
                matrix[0][j] = 0

        # 根据flag_col0更新第一列
        if flag_col0:
            for i in range(m):
                matrix[i][0] = 0

     

4.2 方法三:使用一个标记变量

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        m, n = len(matrix), len(matrix[0])

        # 只使用一个标记变量记录第一列是否原本存在 0
        flag_col0 = False
        
        # 第一次遍历:用matrix的第一行和第一列记录sub_matrix零出现的位置
        for i in range(m): # 从0开始遍历行
            # 只使用一个标记变量记录第一列是否原本存在 0
            if matrix[i][0] == 0:
                flag_col0 = True

            for j in range(1, n ): # 从1开始遍历列
                if matrix[i][j] == 0:
                    matrix[i][0] = matrix[0][j] = 0 
        
        # 第二次遍历根据0的位置更新matrix
        for i in range(m-1, -1, -1): # 从0开始倒序遍历行
            for j in range(1, n ): # 从1开始遍历列
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0
            if flag_col0:
                matrix[i][0] = 0

 

5. 复杂度分析

5.1 方法一:使用标记数组

  • 时间复杂度 O ( m n ) O(mn) O(mn),其中 m m m 是矩阵的行数, n n n 是矩阵的列数。我们至多只需要遍历该矩阵两次。
  • 空间复杂度 O ( m + n ) O(m+n) O(m+n),其中 m m m是矩阵的行数, n n n 是矩阵的列数。我们需要分别记录每一行或每一列是否有零出现。

5.2 方法二:使用两个标记变量

  • 时间复杂度 O ( m n ) O(mn) O(mn),其中 m m m 是矩阵的行数, n n n 是矩阵的列数。我们至多只需要遍历该矩阵两次。

  • 空间复杂度O(1),额外需要两个标记变量的存储空间。

5.2 方法三:使用一个标记变量

  • 时间复杂度 O ( m n ) O(mn) O(mn),其中 m m m 是矩阵的行数, n n n 是矩阵的列数。我们至多只需要遍历该矩阵两次。

  • 空间复杂度O(1),额外需要一个标记变量的存储空间。

 

6. 总结

python range 倒序:

m =5
for i in range(m-1, -1, -1):
    print(i, end = ' ')

4 3 2 1 0

m =5
for i in range(m-1, 0, -1):
    print(i, end = ' ')

4 3 2 1

更新矩阵:

  • 在更新矩阵时,要注意更新矩阵的顺序,避免标记数组被提前更新
for i in range(m-1, -1, -1): # 从0开始倒序遍历行

for循环合并:

  • 当存在两个或者多个for循环的循环区间相同时,应该将其合并
for i in range(m-1, -1, -1): # 从0开始倒序遍历行
            for j in range(1, n ): # 从1开始遍历列
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0
            if flag_col0:
                matrix[i][0] = 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值