一. 题目

二. 思路

  • 我们可以用矩阵的第一行和第一列去标记某行某列是否有0,以达到 O(1) 的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 0。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含 0。

  • 在实际代码中,我们首先预处理出两个标记变量,接着使用其他行与列去处理第一行与第一列,然后反过来使用第一行与第一列去更新其他行与列,最后使用两个标记变量更新第一行与第一列即可。

三. 代码

class Solution
{
    public void setZeroes(int[][] matrix)
    {
        int n = matrix.length, m = matrix[0].length;
        boolean r0 = false, c0 = false;//第0行和列是否有0

        //处理0行列标记
        for (int i = 0; i < m; ++i)
            if (matrix[0][i] == 0)
            {
                r0 = true;
                break;
            }
        for (int i = 0; i < n; ++i)
            if (matrix[i][0] == 0)
            {
                c0 = true;
                break;
            }

        //标记哪行哪列存在0
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j)
                if (matrix[i][j] == 0)
                {
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }

        //置矩阵非0行列为0
        for (int i = 1; i < n; ++i)
            for (int j = 1; j < m; ++j)
                if (matrix[i][0] == 0 || matrix[0][j] == 0)
                    matrix[i][j] = 0;

        //置0行0列为0
        if (r0)
        {
            for (int i = 0; i < m; ++i)
                matrix[0][i] = 0;
        }

        if (c0)
        {
            for (int i = 0; i < n; ++i)
                matrix[i][0] = 0;
        }
    }
}