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

执行时间如下:

相关推荐
深圳市快瞳科技有限公司27 分钟前
小场景大市场:猫狗识别算法在宠物智能设备中的应用
算法·计算机视觉·宠物
liulilittle1 小时前
OPENPPP2 —— IP标准校验和算法深度剖析:从原理到SSE2优化实现
网络·c++·网络协议·tcp/ip·算法·ip·通信
superlls3 小时前
(算法 哈希表)【LeetCode 349】两个数组的交集 思路笔记自留
java·数据结构·算法
田里的水稻4 小时前
C++_队列编码实例,从末端添加对象,同时把头部的对象剔除掉,中的队列长度为设置长度NUM_OBJ
java·c++·算法
纪元A梦4 小时前
贪心算法应用:保险理赔调度问题详解
算法·贪心算法
Jayden_Ruan5 小时前
C++逆向输出一个字符串(三)
开发语言·c++·算法
点云SLAM6 小时前
C++ 常见面试题汇总
java·开发语言·c++·算法·面试·内存管理
叙白冲冲6 小时前
哈希算法以及面试答法
算法·面试·哈希算法
YuTaoShao7 小时前
【LeetCode 每日一题】1277. 统计全为 1 的正方形子矩阵
算法·leetcode·矩阵
古译汉书7 小时前
嵌入式铁头山羊stm32-ADC实现定时器触发的注入序列的单通道转换-Day26
开发语言·数据结构·stm32·单片机·嵌入式硬件·算法