Leetcode刷题记录29——矩阵置零

题源:https://leetcode.cn/problems/set-matrix-zeroes/description/?envType=study-plan-v2&envId=top-100-liked

题目描述:

思路一:

💡 解题思路

本题中我们采用如下策略:

  • 第一次遍历整个矩阵,记录所有值为 0 的元素的 行号列号
  • 使用两个集合 x_sety_set 分别保存需要置零的行索引和列索引。
  • 第二次分别对这些行和列进行置零操作。
    虽然这种方法没有做到最优的空间复杂度(O(1)),但它逻辑清晰、易于理解,是非常实用的一种实现方式。

✅ 具体实现步骤
第一步:获取矩阵尺寸

python 复制代码
m = len(matrix)      # 行数
n = len(matrix[0])   # 列数

首先我们通过 len() 获取矩阵的行数和列数,便于后续遍历。

第二步:记录所有需要置零的行和列

python 复制代码
x_set = set()  # 存储需要置零的行
y_set = set()  # 存储需要置零的列

for i in range(m):
    for j in range(n):
        if matrix[i][j] == 0:
            x_set.add(i)
            y_set.add(j)

这里我们使用了两个集合来记录出现 0 的行和列,这样可以避免重复处理。

⚠️ 注意:使用集合是为了自动去重,避免多次添加相同的行或列。

第三步:将对应的行全部置为 0

python 复制代码
for i in x_set:
    for j in range(n):
        matrix[i][j] = 0

对每一个需要置零的行 i,我们从第 0 列到第 n-1 列依次设置为 0。

第四步:将对应的列全部置为 0

python 复制代码
for j in y_set:
    for i in range(m):
        matrix[i][j] = 0

同理,对每一个需要置零的列 j,我们从第 0 行到第 m-1 行依次设置为 0。

⏱️ 时间与空间复杂度分析
时间复杂度:O(m * n) ,每个元素最多被访问两次
空间复杂度:O(m + n),使用了两个集合存储行和列

✅ 优点:逻辑清晰、实现简单

❌ 缺点:未达到 O(1) 空间复杂度(进阶可优化)

代码如下:

python 复制代码
class Solution(object):
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        zero_index = []
        m = len(matrix)      # 行数
        n = len(matrix[0])   # 列数
        x_set= set()
        y_set = set()

        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0:
                    x_set.add(i)
                    y_set.add(j)
        
        # 将对应的行置零
        for i in x_set:
            for j in range(n):
                matrix[i][j] = 0

        # 将对应的列置零
        for j in y_set:
            for i in range(m):
                matrix[i][j] = 0

执行时间如下:

思路二:

核心思想:

利用矩阵的第一行和第一列来标记对应的列和行是否需要置零,这样就不需要额外的空间了。

但需要注意的是,第一行和第一列本身也可能被置零,所以我们需要用两个布尔变量来单独记录它们的状态。

✅ 具体实现步骤

第一步:初始化标记变量

python 复制代码
first_row_has_zero = False  # 是否第一行需要置零
first_col_has_zero = False  # 是否第一列需要置零

这两个变量用于最后判断是否要将第一行或第一列整体置零。

第二步:检查第一列中是否有 0

python 复制代码
for i in range(m):
    if matrix[i][0] == 0:
        first_col_has_zero = True
        break

只要第一列中有一个 0,说明整列都要置零。

第三步:检查第一行中是否有 0

python 复制代码
for j in range(n):
    if matrix[0][j] == 0:
        first_row_has_zero = True
        break

同理,只要第一行中有 0,就说明整行要置零。

第四步:使用第一行和第一列作为标记数组

从第二行、第二列开始遍历整个矩阵:

python 复制代码
for i in range(1, m):
    for j in range(1, n):
        if matrix[i][j] == 0:
            matrix[i][0] = 0
            matrix[0][j] = 0

如果当前元素是 0,就把该行首和列首置零,表示这一行/列后续都需要置零。

第五步:根据标记置零中间部分

python 复制代码
for i in range(1, m):
    if matrix[i][0] == 0:
        for j in range(1, n):
            matrix[i][j] = 0

for j in range(1, n):
    if matrix[0][j] == 0:
        for i in range(1, m):
            matrix[i][j] = 0
  • 对于每一行,如果它的第一个元素是 0,则整行置零;
  • 对于每一列,如果它的第一个元素是 0,则整列置零。

第六步:处理第一行和第一列

python 复制代码
if first_row_has_zero:
    for j in range(n):
        matrix[0][j] = 0

if first_col_has_zero:
    for i in range(m):
        matrix[i][0] = 0

最后再根据最开始保存的两个布尔值来决定是否把第一行和第一列也置零。

⏱️ 时间与空间复杂度分析
时间复杂度:O(m * n) ,每个元素最多被访问两次
空间复杂度:O(1) ,只使用了常数级额外空间

代码如下:

python 复制代码
class Solution(object):
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        m = len(matrix)      # 行数
        n = len(matrix[0])   # 列数

        first_row_has_zero = False  # 是否第一行需要置零
        first_col_has_zero = False  # 是否第一列需要置零

        # 检查第一列是否有 0
        for i in range(m):
            if matrix[i][0] == 0:
                first_col_has_zero = True
                break

        # 检查第一行是否有 0
        for j in range(n):
            if matrix[0][j] == 0:
                first_row_has_zero = True
                break

        # 使用第一行和第一列作为标记数组
        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[i][0] = 0
                    matrix[0][j] = 0

        # 根据标记置零中间部分
        for i in range(1, m):
            if matrix[i][0] == 0:
                for j in range(1, n):
                    matrix[i][j] = 0

        for j in range(1, n):
            if matrix[0][j] == 0:
                for i in range(1, m):
                    matrix[i][j] = 0

        # 处理第一行
        if first_row_has_zero:
            for j in range(n):
                matrix[0][j] = 0

        # 处理第一列
        if first_col_has_zero:
            for i in range(m):
                matrix[i][0] = 0

执行时间如下:

相关推荐
张人玉2 小时前
西门子PLC地址知识点
算法·西门子plc
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2025.12.17 题目:3573.买卖股票的最佳时机Ⅴ
笔记·算法·leetcode
榮十一2 小时前
10道SQL练习题及答案
数据库·sql·算法
l1t2 小时前
Javascript引擎node bun deno比较
开发语言·javascript·算法·ecmascript·bun·精确覆盖·teris
仰泳的熊猫2 小时前
1094 The Largest Generation
数据结构·c++·算法·pat考试
LYFlied2 小时前
【每日算法】LeetCode 739. 每日温度:从暴力遍历到单调栈的优雅解决
前端·算法·leetcode·面试·职场和发展
铭哥的编程日记2 小时前
DFS + 剪枝 解决 全排列系列问题 (所有题型)
算法·深度优先·剪枝
yaoh.wang2 小时前
力扣(LeetCode) 67: 二进制求和 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·跳槽
Java后端的Ai之路2 小时前
【分析式AI】-LightGBM算法命名解释
人工智能·算法·机器学习·aigc·分析式ai
夏鹏今天学习了吗2 小时前
【LeetCode热题100(74/100)】跳跃游戏
算法·leetcode·游戏