要求用O(1)空间实现,O(nm)时间则是遍历矩阵每个元素必要的。
题目原意为若matrix[i][j]为0, 则第i行和第j列要变为0. 只有original 0才会导致这样的变化,那些被改变的元素不能导致全行全列变为0.
矩阵有n行m列,朴素的方法是用n+m个变量记录那些行列要变成0. 这是O(n+m)空间。
但考虑到有性质:若matrix[i][j]为0, 必会使matrix[i][0]和matrix[0][j]变为0. 所以若matrix[i][j]为0, 我们将matrix[i][0], matrix[0][j]赋值为0, 用矩阵本身记录要发生的变化。
在此需要特判第0行和第0列的元素,例如matrix[0][3]为0, 我们不能马上将matrix[0][0]设置为0, 如若这样,进行矩阵赋值时,对于matrix[0][0], 我们不知是将第0行赋值为0, 还是第0列赋值为0. 由此我们再引入first_row, first_column记录第0行和第0列是否应该被赋值为0.
根本原因是:matrix[0][0~m-1], matrix[0~n-1][0] 总共只有n-m-1个元素,我们却想用它记录n+m行列的状态,所以必须要引入新的变量(first_row, first_column)。
代码:
class Solution
{
public:
void setZeroes(vector<vector<int> > &matrix)
{
bool first_row=false, first_column=false;
size_t n=matrix.size(), m=matrix[0].size();
for (size_t j = 0; j < m; ++ j)
{
if (matrix[0][j] == 0)
{
first_row = true;
}
}
for (size_t i = 0; i < n; ++ i)
{
if (matrix[i][0] == 0)
{
first_column = true;
}
}
for (size_t i = 1; i < n; ++ i)
{
for (size_t j = 1; j < m; ++ j)
{
if (matrix[i][j] == 0)
{
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for (size_t j = 1; j < m; ++ j)
{
if (matrix[0][j] == 0)
{
for (size_t i = 1; i < n; ++ i)
{
matrix[i][j] = 0;
}
}
}
for (size_t i = 1; i < n; ++ i)
{
if (matrix[i][0] == 0)
{
for (size_t j = 1; j < m; ++ j)
{
matrix[i][j] = 0;
}
}
}
if (first_row == true)
{
for (size_t j = 0; j < m; ++ j)
{
matrix[0][j] = 0;
}
}
if (first_column == true)
{
for (size_t i = 0; i < n; ++ i)
{
matrix[i][0] = 0;
}
}
}
};