
错误:不能边遍历矩阵 边把遇到的0给直接置零 因为后面再遍历到这个新生成的0时 会误认为它是原本的0 又把它的行和列给置零 最后就是整个矩阵都变成0了 结果完全错
正确的逻辑:先记录哪些行和列需要置零 全部记录完成后 再统一把这些行和列给置零
法一标记数组法:
法二 两个标记变量:
首先上来先判断第一行第一列有没有零,有0 true 没0false
然后再遍历除了第一行第一列的矩阵。如果m[i][j]某个元素为0,那么就让m[i][0]第1列第i行的元素为0,让m[0][j]的元素为0 ,即让第1行第j列的元素为0.这里就体现了第一行第一列的起到标记的作用,不参与遍历。然后遍历结束后,标记完了,继续第二次遍历,只要
这一行的行标记是 0(matrix [i][0] == 0) OR 这一列的列标记是 0(matrix [0][j] == 0)
就把 matrix[i][j] = 0。最后在处理第一行第一列,如果前面为true 就置零 如果false就不变。
如果边遍历边置零的话:比如下面的原始矩阵,遍历到(1,1)的时候有0,如果直接置零,此时就变成了图二的样子,但是此刻的遍历还没有结束,遍历到(1,2)的时候 发现又有零 又会置零 所以不行。


cpp
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size();//行数
int n = matrix[0].size();//列数
//记录第一行第一列的状态
int col0 =false,row0 =false;
for(int i = 0;i<m;i++){
//遍历第一列
if(matrix[i][0]==0){
col0 = true;
}
}
for(int j = 0;j<n;j++){
//遍历第一行
if(matrix[0][j] == 0){
row0 = true;
}
}
//接着遍历除了第一行第一列的东西
for(int i = 1;i<m;i++){
for(int j = 1;j<n;j++){
//如果有0则标记
if(matrix[i][j]==0){
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
//继续遍历 如果标记是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(col0){
for(int i =0;i<m;i++){
matrix[i][0] = 0;
}
}
if(row0){
for(int j = 0;j<n;j++){
matrix[0][j] = 0;
}
}
}
};