0
点赞
收藏
分享

微信扫一扫

力扣第 73 题 矩阵置零

天天天蓝loveyou 2024-12-02 阅读 8

题目描述

给定一个 m x n 的矩阵 matrix,其中每个元素不是 0 就是非零整数。

如果一个元素是 0,则将它所在的整行和整列都置为 0。请你实现这个操作,要求 空间复杂度 O(1)


示例

示例 1:

输入

matrix = [
[1,1,1],
[1,0,1],
[1,1,1]
]

输出

[
[1,0,1],
[0,0,0],
[1,0,1]
]

示例 2:

输入

matrix = [
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]

输出

[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]

解题思路

1. 暴力法

  • 最直观的做法是,遍历整个矩阵,遇到 0 时,标记该位置所在的行和列,并将这些行和列的所有元素设置为 0。
  • 这种方法的空间复杂度是 O(m + n),因为我们需要额外的数组来记录需要置零的行和列。

2. 空间优化(O(1) 空间复杂度)

  • 题目要求空间复杂度是 O(1),即不能使用额外的数组(如布尔数组)来存储行和列的状态。我们可以在原地进行修改。
  • 通过使用矩阵的 第一行第一列 来记录该行和该列是否需要置零。
  • 第一行第一列 本身也可能包含零,所以需要额外的变量来记录它们是否需要置零。

3. 优化步骤

  1. 检查第一行和第一列:我们需要一个标志来记录第一行和第一列是否应该被置零。
  2. 遍历矩阵:从矩阵的第二行和第二列开始,如果 matrix[i][j] == 0,就将 matrix[i][0]matrix[0][j] 设置为 0,表示该行和列应该被置零。
  3. 根据标志置零:根据第一行和第一列的标记,更新矩阵中的其它元素。
  4. 处理第一行和第一列:最后根据记录的标志更新第一行和第一列。

实现代码:

#include <stdio.h>

void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
    int m = matrixSize; // 矩阵的行数
    int n = *matrixColSize; // 矩阵的列数

    int firstRowZero = 0, firstColZero = 0;

    // 检查第一行是否需要置零
    for (int j = 0; j < n; j++) {
        if (matrix[0][j] == 0) {
            firstRowZero = 1;
            break;
        }
    }

    // 检查第一列是否需要置零
    for (int i = 0; i < m; i++) {
        if (matrix[i][0] == 0) {
            firstColZero = 1;
            break;
        }
    }

    // 使用第一行和第一列标记其他行列需要置零
    for (int i = 1; i < m; i++) {
        for (int j = 1; j < n; j++) {
            if (matrix[i][j] == 0) {
                matrix[i][0] = 0; // 标记该行
                matrix[0][j] = 0; // 标记该列
            }
        }
    }

    // 根据标记的行列置零
    for (int i = 1; i < m; i++) {
        for (int j = 1; j < n; j++) {
            if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                matrix[i][j] = 0;
            }
        }
    }

    // 处理第一行
    if (firstRowZero) {
        for (int j = 0; j < n; j++) {
            matrix[0][j] = 0;
        }
    }

    // 处理第一列
    if (firstColZero) {
        for (int i = 0; i < m; i++) {
            matrix[i][0] = 0;
        }
    }
}

int main() {
    int m = 3, n = 4;
    
    // 动态分配内存
    int** matrix = (int**)malloc(m * sizeof(int*));
    for (int i = 0; i < m; i++) {
        matrix[i] = (int*)malloc(n * sizeof(int));
    }

    // 初始化矩阵
    int matrixData[3][4] = {
        {0, 1, 2, 0},
        {3, 4, 5, 2},
        {1, 3, 1, 5}
    };

    // 将数据复制到动态分配的矩阵中
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i][j] = matrixData[i][j];
        }
    }

    setZeroes(matrix, m, &n);

    // 打印结果
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    // 释放内存
    for (int i = 0; i < m; i++) {
        free(matrix[i]);
    }
    free(matrix);

    return 0;
}

步骤说明:

  1. 检查第一行和第一列是否需要置零:
    • 使用变量 firstRowZerofirstColZero 来分别标记第一行和第一列是否包含零。
  2. 遍历矩阵并标记需要置零的行和列:
    • 从第二行第二列开始,遍历矩阵。如果遇到 matrix[i][j] == 0,就将 matrix[i][0]matrix[0][j] 设置为零,表示第 i 行和第 j 列需要置零。
  3. 根据标记的行列更新矩阵:
    • 再次遍历矩阵,按照第一行和第一列的标记将相应位置的元素置零。
  4. 处理第一行和第一列:
    • 如果 firstRowZero 为 1,则将第一行所有元素置零。
    • 如果 firstColZero 为 1,则将第一列所有元素置零。

时间复杂度与空间复杂度

时间复杂度:

  • 遍历矩阵两次,因此时间复杂度是 O(m * n),其中 mn 分别是矩阵的行数和列数。

空间复杂度:

  • 我们仅使用了常量的额外空间(firstRowZerofirstColZero),因此空间复杂度是 O(1),符合题目要求。
举报

相关推荐

0 条评论