73. Set Matrix Zeroes

仅供自己学习

 

思路:

第一个O(M+N)的空间复杂度。因为是原地算法,所以当我们根据0的位置更改为0后,我们再次遍历到0就会无法判断原来就是0还是更改后为0的。所以需要一个M*N的数据结构来记录原来为0的位置。

第一种 copy一个matrix,然后遍历copy的,如果有0就在matrix更改即可。

代码:

 1 class Solution {
 2 public:
 3     void setZeroes(vector<vector<int>>& matrix) {
 4         if(matrix.size()==0||matrix[0].size()==0) return;
 5         vector<vector<int>> newM(matrix);
 6        const int R = matrix.size(), C = matrix[0].size();
 7        for(int r=0;r<R;++r){
 8            for(int c=0;c<C;++c){
 9                if(newM[r][c] ==0 ){
10                    for(int j=0; j<C ;++j) matrix[r][j]=0;
11                    for(int i=0;i<R ;++i) matrix[i][c]=0;
12                }
13            }
14        }
15     }
16 };

 

上面这种是边遍历边改。还有一种是全部遍历完再更改。每次遍历到0就存入队列,之后再取出来全部化0即可。

 1 class Solution {
 2 public:
 3     void setZeroes(vector<vector<int>>& matrix) {
 4         if(matrix.size()==0||matrix[0].size()==0) return;
 5         const int R=matrix.size(),C=matrix[0].size();
 6         queue<pair<int,int>> q;
 7         for(int r = 0; r<R; ++r){
 8             for(int c = 0; c<C; ++c){
 9                 if(matrix[r][c]==0) q.push({r,c});
10             }
11         }
12 
13         while(!q.empty()){
14             auto temp=q.front();q.pop();
15             for(int j=0;j<C; ++j) matrix[temp.first][j]=0;
16             for(int i= 0; i < R; ++i)matrix[i][temp.second]=0;
17         }
18     }
19 };

 

另一种是M+N空间复杂度的方法。

用一个M长度的数组和N长度的数组存为0的位置。然后再遍历,更改为0的条件是 M[ i ]||N[ j ]。为什么只要求一个为1即可。这样才能把一行或者一列的置0。例如M[2]=N[3]=1,那么每次行数增加,列数增加到3时才能将一列的置0,否则只能将一行置零。

代码:

 1 class Solution {
 2 public:
 3     void setZeroes(vector<vector<int>>& matrix) {
 4         if(matrix.size()==0||matrix[0].size()==0) return;
 5         const int R=matrix.size(),C=matrix[0].size();
 6         vector<int> N(R), M(C);
 7         for(int r = 0; r<R; ++r){
 8             for(int c = 0; c<C; ++c){
 9                 if(matrix[r][c]==0) N[r]=M[c]=1;
10             }
11         }
12         for(int i=0;i<R;++i){
13             for(int j=0;j<C;++j){
14                 if(N[i]||M[j])  matrix[i][j]=0;
15             }
16         }
17     }
18 };

 

如果我们将矩阵 第一行第一列当作上面的两个N,M数组,就能达成O(1)的复杂度,但是有个问题就是第一行第一列改成0后那么如何判断他原来有没有0呢?所以我们用两个BOOL变量用来存储,第一行第一列有0就true,最后根据是否为true来决定是否将所有第一列和第一行元素置0。

这样做对的原因是,如果第一行,第一列没有0,那么我们在某个位置找到0后,例如[2][3],那么[0][3]和[2][0]会被置0,而我们题目要求时第二行第三列都会置0,所以[0][3],[2][0]提前置零并不会有问题。如果第一行,第一列有0,最后再把第一行,第一列置0同样不会影响结果。

代码:

 1 class Solution {
 2 public:
 3     void setZeroes(vector<vector<int>>& matrix) {
 4         if(matrix.size()==0||matrix[0].size()==0) return;
 5         const int R=matrix.size(),C=matrix[0].size();
 6         bool flag_row0=false,flag_col0=false;
 7         for(int i=0;i<C;++i){
 8             if(matrix[0][i]==0) flag_row0=true;
 9         }
10         for(int j=0;j<R;++j){
11             if(matrix[j][0]==0) flag_col0=true;
12         }
13         for(int i=1;i<R;++i){
14             for(int j=1;j<C;++j){
15                 if(matrix[i][j]==0) matrix[0][j]=matrix[i][0]=0;
16             }
17         }
18         for(int i=1;i<R;++i){
19             for(int j=1;j<C;++j){
20                 if(!matrix[0][j]||!matrix[i][0]) matrix[i][j]=0;
21             }
22         }
23         if(flag_row0){
24             for(int i=0;i<C;++i) matrix[0][i]=0;
25         }
26          if(flag_col0){
27             for(int i=0;i<R;++i) matrix[i][0]=0;
28         }
29     }
30 };

 

posted @ 2021-03-29 17:04  Mrsdwang  阅读(51)  评论(0)    收藏  举报