Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.
Input: [ [1,1,1], Output: [ [1,0,1],
[1,0,1], [0,0,0],
[1,1,1] ] [1,0,1] ]
Follow up:
- A straight forward solution using O(mn) space is probably a bad idea.
- A simple improvement uses O(m + n) space, but still not the best solution.
- Could you devise a constant space solution?
解:
题目意思很简单,就是对于一个矩阵,只要 i, j 位置为0,就将第 i 行,第 j 列都设为 0。
题目的主要目的在于follow up中讲到的,m * n 大小的空间复杂度是一个很差的方法(也就是弄一个新的一样大的矩阵重新赋值),用 m + n 的空间复杂度也不是最好的solution,能不能有更好的方法。
首先我是先实现了 O(m + n) space 的方法,也就是用两个vector记录哪些行要变为0,哪些列要变为0,然后修改矩阵即可。
void setZeroes(vector<vector<int>>& matrix)
{
int rows = matrix.size(), cols = matrix[0].size();
vector<int> zero_col, zero_row;
// 必须遍历所有位置
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
{
if(matrix[i][j] == 0)
{
zero_col.push_back(j); // 第 j 列有 0
zero_row.push_back(i); // 第 i 行有 0
}
}
for(int r : zero_row)
for(int& m : matrix[r])
m = 0;
for(int c : zero_col)
for(int i = 0; i < rows; i++)
matrix[i][c] = 0;
}
上述代码是可以AC的,不过只beat 22% 的cpp submission,且不是题目要求的最好的方法。
对于这种矩阵我第一想法就是用负数表示要变成0的数,然后最后将所有负数变为0。AC代码如下:
void setZeroes(vector<vector<int>>& matrix)
{
int rows = matrix.size(), cols = matrix[0].size();
bool flag = false;
// 必须遍历所有位置
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
{
if(matrix[i][j] == 0)
{
flag = true;
for(int t = 0; t < rows; t++) // 这一列非0元素全设为-1, 不能修改0
if(matrix[t][j] != 0)
matrix[t][j] = -99999;
for(int t = 0; t < cols; t++) // 这一行非0元素全设为-1, 不能修改0
if(matrix[i][t] != 0)
matrix[i][t] = -99999;
}
}
if(flag == false)
return ;
for(auto& r : matrix)
for(auto& i : r)
if(i == -99999)
i = 0;
}
虽然过了,而且也没有用多余的空间,但是其实是有bug的,因为矩阵测试用例中是有负数的,只不过没有-99999而已。