矩阵置零

GitHub跳转原题关系图返回列表

用首行/首列充当标记位,先记录首行首列是否含零,再标记并回填,O(1) 额外空间。

OJ: leetcodecn

题目 ID: set-matrix-zeroes

难度:普及+/提高

标签:数组矩阵cpppython

日期: 2026-07-28 22:05

题意

m×n 矩阵,如果某元素为 0,将其所在行和列全部置零。原地修改。

思路

用额外行列集合记录零位置 O(m+n) 空间。O(1) 空间优化:用矩阵首行首列作为标记位,先单独记录首行首列本身是否含零,再用首行首列标记其他行列是否有零,最后回填。

代码

cpp
/**
 * Author by Rainboy
 */
// main.cpp:用首行/首列充当标记,O(1) 额外空间。
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    void setZeroes(vector<vector<int>> &matrix) {
        int m = matrix.size(), n = matrix[0].size();
        bool row0 = false, col0 = false;
        for (int j = 0; j < n; j++)
            if (matrix[0][j] == 0)
                row0 = true;
        for (int i = 0; i < m; i++)
            if (matrix[i][0] == 0)
                col0 = true;
        for (int i = 1; i < m; i++)
            for (int j = 1; j < n; j++)
                if (matrix[i][j] == 0)
                    matrix[i][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 (row0)
            for (int j = 0; j < n; j++)
                matrix[0][j] = 0;
        if (col0)
            for (int i = 0; i < m; i++)
                matrix[i][0] = 0;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int m, n;
    cin >> m >> n;
    vector<vector<int>> a(m, vector<int>(n));
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            cin >> a[i][j];
    Solution().setZeroes(a);
    for (auto &row : a) {
        for (int x : row)
            cout << x << ' ';
        cout << '\n';
    }
    return 0;
}
python
#!/usr/bin/env python3
from typing import List


class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        m, n = len(matrix), len(matrix[0])
        row0 = any(matrix[0][j] == 0 for j in range(n))
        col0 = any(matrix[i][0] == 0 for i in range(m))
        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[i][0] = matrix[0][j] = 0
        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
        if row0:
            for j in range(n):
                matrix[0][j] = 0
        if col0:
            for i in range(m):
                matrix[i][0] = 0


def main() -> None:
    m, n = map(int, input().split())
    a = [list(map(int, input().split())) for _ in range(m)]
    Solution().setZeroes(a)
    for row in a:
        print(*row)


if __name__ == "__main__":
    main()

复杂度

  • 时间复杂度:O(mn),遍历矩阵两次。
  • 空间复杂度:O(1)。

总结

"借用已有空间作标记"是原地算法的常见技巧,关键在于防止标记本身被提前覆盖。