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

执行时间如下:

相关推荐
.格子衫.5 分钟前
014枚举之指针尺取——算法备赛
java·c++·算法
明月看潮生20 分钟前
青少年编程与数学 02-018 C++数据结构与算法 24课题、密码学算法
c++·算法·青少年编程·密码学·编程与数学
小小白?30 分钟前
64.搜索二维矩阵
数据结构·线性代数·算法·矩阵
小羊在奋斗34 分钟前
【LeetCode 热题 100】矩阵置零 / 螺旋矩阵 / 旋转图像 / 搜索二维矩阵 II
算法·leetcode·矩阵
wuqingshun31415938 分钟前
蓝桥杯 17. 通电
c++·算法·职场和发展·蓝桥杯·深度优先·动态规划
卷卷的小趴菜学编程1 小时前
算法篇-----滑动窗口
数据结构·算法·双指针·滑动窗口·哈希表·数组相关
zxctsclrjjjcph1 小时前
【动态规划】子序列问题
开发语言·c++·算法·动态规划·力扣
对对对,你说啥都对1 小时前
用输入输出变量根据超稳定性理论设计模型参考自适应系统
算法·自适应控制·超稳定性理论
Sheep Shaun2 小时前
C++ STL简介:构建高效程序的基石
开发语言·数据结构·c++·算法
点云SLAM2 小时前
C++ 中二级指针的正确释放方法
开发语言·数据结构·c++·人工智能·算法