题目如下:
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.
click to show follow up.
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?
思考分析:
一开始很容易想到O(mn)的做法。再另外开辟一个同样的矩形来存储改变后的值。
也很容易想到O(m+n)的做法,就是用O(m)的空间记下有哪些行需要被修改的,用O(n)的空间记下有哪些列需要被修改的,然后直接在原矩阵上进行改变。
比较困难的是,constant space做法比较难想到。我一开始觉得,无论怎样,都需要O(m+n)的空间来记录到底有哪些行需要被修改和哪些列需要被修改,所以不可能做到用常数的空间记录啊。看了网上的答案,发现这道题目比较巧妙的地方在于,你可以复用矩阵本身的空间来记录到底有哪些行需要被修改和哪些列需要被修改,而不是开辟新的空间,这样就实现了常量空间。
具体做法是,首先用两个变量记录分别下第0行是否包含0,第0列是否包含0.记录完之后,第1行和第1列形成的O(m+n)的空间就可以当做存储空间,用来记录矩阵的剩下的n-1行和剩下的n-1是否包含0了。
我的代码:
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
int row=(int)matrix.size();
if(row==0)
return;
int col=(int)matrix[0].size();
if(col==0)
return ;
bool first_row_has_zero=false;
bool first_col_has_zero=false;
//check first col
for(int i=0;i<row;i++)
if(matrix[i][0]==0){
first_col_has_zero=true;
break;
}
//check first row
for(int i=0;i<col;i++)
if(matrix[0][i]==0){
first_row_has_zero=true;
break;
}
//record 2~n-1 row in first col
for(int i=1;i<row;i++){
for(int j=1;j<col;j++){
if(matrix[i][j]==0){
matrix[i][0]=0;
break;
}
}
}
//record 2~n-1 col in first row
for(int i=1;i<col;i++){
for(int j=1;j<row;j++){
if(matrix[j][i]==0){
matrix[0][i]=0;
break;
}
}
}
//set row 2~n-1
for(int i=1;i<row;i++){
if(matrix[i][0]==0)
for(int j=0;j<col;j++)
matrix[i][j]=0;
}
//set col 2~n-1
for(int i=1;i<col;i++){
if(matrix[0][i]==0)
for(int j=0;j<row;j++)
matrix[j][i]=0;
}
// set row 1 and col 1
if(first_row_has_zero)
for(int j=0;j<col;j++)
matrix[0][j]=0;
if(first_col_has_zero)
for(int j=0;j<row;j++)
matrix[j][0]=0;
}
};
update: 2015-02-26
// 95ms 更新了update相应的行或者相应的列为零的部分。
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
int rows = matrix.size();
if (rows == 0)
return;
int cols = matrix[0].size();
int row_zero_has_zero = false;
int col_zero_has_zero = false;
for (int i = 0; i < cols; ++i) { //一开始思维混乱了,错写为了for (int i = 1; i < cols; ++i)
if (matrix[0][i] == 0)
row_zero_has_zero = true;
}
for (int i = 0; i < rows; ++i) { //一开始思维混乱了,错写为了for (int i = 1; i < cols; ++i)
if (matrix[i][0] == 0)
col_zero_has_zero = true;
}
for (int i = 1; i < cols; ++i) {
for (int j = 1; j < rows; ++j) {
if (matrix[j][i] == 0) {
matrix[0][i] = 0;
break;
}
}
}
for (int i = 1; i < rows; ++i) {
for (int j = 1; j < cols; ++j) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
break;
}
}
}
for (int i = 1; i < rows; ++i) {
for (int j = 1; j < cols; ++j) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
if (row_zero_has_zero) {
for (int j = 0; j <cols; ++j) {
matrix[0][j] = 0;
}
}
if (col_zero_has_zero) {
for (int j = 0; j <rows; ++j) {
matrix[j][0] = 0;
}
}
}
};
小结扩展:
(1) 这道题的本质不是一道程序题,而是一道思维题目。需要think outside the box,空间用得省一些,可以复用已经有的空间,从而最大限度地减少对新空间的占用。
(2) CC 150也有这道题目,这里写了个版本, 最省可以省到连两个变量(row_zero_has_zero 和 col_zero_has_zero)都不需要使用了。