当矩阵中有元素是0时,就将它所在的那一行和那一列全都置为0.
例如:
Input: [ [1,1,1], [1,0,1], [1,1,1] ] Output: [ [1,0,1], [0,0,0], [1,0,1] ]
难度:【medium】
思考:最初想到的在遍历矩阵每个元素时,如果该元素是0,那么就将它所在的行和列的元素都改为0,可是再一想,发现再遍历下面的元素时,会区分不了是原来就是0,还是才改为0的。这是需要注意的地方。下面有三种方法:
方法1:比较容易想到,而且写出来一般不会出现什么bug. 利用两个set存放需要置0的行和列, 使用set是为了去重。
void setZeroes(vector<vector<int>>& matrix) {
std::set<int> zero_rows;
std::set<int> zero_cols;
for (int i = 0; i < matrix.size(); ++i) {
for (int j = 0; j < matrix[0].size(); ++j) {
if (matrix[i][j] == 0) {
zero_rows.insert(i);
zero_cols.insert(j);
}
}
}
for (int i = 0; i < matrix.size(); ++i) {
for (int j = 0; j < matrix[0].size(); ++j) {
if (zero_rows.count(i) > 0 || zero_cols.count(j) > 0) {
matrix[i][j] = 0;
}
}
}
}
空间:O(M+N)
时间:O(M*N)
方法2:也是两次遍历矩阵,不过不需要额外的空间,第一次遍历矩阵时,把所有需要变为0的元素标记出来,第二次遍历时,再把那些标记的元素置为0. 这样做就是为了区分哪些元素所在的行和列需要改为0。
void setZeroes(vector<vector<int>>& matrix) {
int MODIFIED = -1000000;
int rows = matrix.size();
int cols = matrix[0].size();
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (matrix[i][j] == 0) {
for (int k = 0; k < rows; ++k) {
// 下面必须判断,否则会影响判断下面的元素是否要标记
if (matrix[k][j] != 0) {
matrix[k][j] = MODIFIED;
}
}
for (int k = 0; k < cols; ++k) {
// 下面必须判断,否则会影响判断下面的元素是否要标记
if (matrix[i][k] != 0) {
matrix[i][k] = MODIFIED;
}
}
}
}
}
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (matrix[i][j] == MODIFIED) {
matrix[i][j] = 0;
}
}
}
}
空间:O(1)
时间:O(M*N*(M+N))
方法3: 也不需要额外的空间,不过容易出现bug。
step1: 先利用两个bool 值 first_row_has_zero 和 first_col_has_zero 记录首行首列是否有为0的元素。
step2: 遍历矩阵,非首行首列的元素,如果某个元素是0,那么就把它对应的首行和首列对应位置置为0来进行标记。
step3: 对非首行首列的元素,按照首行首列的标记,来修改对应元素。
step4: 通过first_row_has_zero 和 first_col_has_zero判断,如果首行/首列最初有为0的元素,那么将首行/首列置为0.
void setZeroes(vector<vector<int>>& matrix) {
if (matrix.size() == 0) { return ; }
int rows = matrix.size();
int cols = matrix[0].size();
// step1
bool first_row_has_zero = false;
bool first_col_has_zero = false;
for (int i = 0; i < cols; ++i) {
if (matrix[0][i] == 0) {
first_row_has_zero = true;
}
}
for (int i = 0; i < rows; ++i) {
if (matrix[i][0] == 0) {
first_col_has_zero = true;
}
}
// step2
for (int i = 1; i < rows; ++i) {
for (int j = 1; j < cols; ++j) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
// step3
// 行置0
for (int i = 1; i < rows; ++i) {
if (matrix[i][0] == 0) {
for (int j = 1; j < cols; ++j) {
matrix[i][j] = 0;
}
}
}
// 列置0
for(int j = 1; j < cols; ++j) {
if (matrix[0][j] == 0) {
for (int i = 1; i < rows; ++i) {
matrix[i][j] = 0;
}
}
}
// step4
// 首行
if (first_row_has_zero) {
for (int j = 0; j < cols; ++j) {
matrix[0][j] = 0;
}
}
// 首列
if (first_col_has_zero) {
for (int j = 0; j < rows; ++j) {
matrix[j][0] = 0;
}
}
}