Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.
Follow up:
Did you use extra space?
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?
思路:
1. 这道题麻烦就麻烦在:矩阵自身含有的0和通过对i行j列置0得到的0,如何区分?这题不无聊,有点趣味!
2. 简单粗暴不优化的方法很容易从脑袋里蹦出来。O(mn)的空间:新建一个m*n的矩阵,初始化-1,然后遍历一遍给的矩阵,发现matrix[i][j]==0,则把对应的新矩阵的i行j列置为0,然后遍历新矩阵,把不为0的位置用旧矩阵同样的位置替代。
2. 空间上肯定可以优化,比如o(m+n),我们对每行每列都要置为相同的数,说明没必要用O(mn)的矩阵保存这么多信息。每一行、每一列只需要一个指示就够了。因此,新建vector< bool> row(m,0)和vector< bool> col(n,0),遍历给的矩阵,遇到0就用对应坐标[i,j]去标识row[i]=1,col[j]=1;最后,再遍历一遍矩阵,对坐标[i,j]查询row和col,if(row[i]=1或col[j]=1)则matrix[i][j]=0;
3. 如果说还可以做成o(1)的空间的话?就只有一些trick的方法了,比如:用给定的矩阵来复用,保存标志位。例如:if(matrix[i][j]==0),则把i行最左边和j列最上边的值置位0;等遍历完一遍后,根据标志位,把整行整列都置0,这又要方位两次。
4. 仔细观察这些思路:都是试图先把所有的0的位置掌握清楚后,再统一归0。从而避免了刚开始面临的问题:如何区分矩阵自身含有的0和通过对i行j列置0得到的0。因此解决问题的核心是:把问题分成两部分先后完成,而不是交叉完成!
5.方法1是空间复用的做法。首先:标记第一行,第一列是否有0;然后遍历除第一行第一列的其他部分,置位第一行第一列;再遍历一次,根据第一行第一列是否为0来置位;最后根据之前关于第一行第一列是否包含0来置位第一行第一列!总共分四步!!!
//方法1:空间复用
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
//
int m=matrix.size();
if(m==0) return;//超级无敌bug,弄晕了半个小时!!!错误写成if(m=0)!!
int n=matrix[0].size();
//把第一行,第一列用来保存标识位
//第一行,第一列是否包含0用标志位单独记录!
int row=0,col=0;
for(int i=0;i<m;i++){
if(matrix[i][0]==0){
row=1;
break;
}
}
for(int j=0;j<n;j++){
if(matrix[0][j]==0){
col=1;
break;
}
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
if(matrix[i][j]==0){
matrix[i][0]=0;
matrix[0][j]=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(row==1){
for(int i=0;i<m;i++)
matrix[i][0]=0;
}
if(col==1){
for(int j=0;j<n;j++)
matrix[0][j]=0;
}
}
};