题目:
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.
题意:
给一个m x n的矩阵,如果某个元素是0,那么就将这个元素所在的行与这个元素所在的列都设为0.
思路:
这道题的一般思路是扫描所有元素,使用一个一维数组line[m]存储哪些行需要设为0,使用一个一维数组row[n]存储哪些列需要设为0.其空间复杂度是O(m+n).如果元素是A[i][j]=0,那么令line[i] = 1(代表第i行需要设为0),令row[j] = 1(代表第j列需要设为0)。
我希望可以降低空间复杂度,因此用了一个long long来使用位操作来存储哪一行需要设为0(能够保存64行的信息,就是说m<= 64才可满足条件),同样也用一个long long来存储哪一列需要设为0(也需要满足n<=64)。代码如下:
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
if(matrix.size() == 0)return;
long long row = 0xffffffffffffffff;
long long column = 0xffffffffffffffff;
int rows = matrix.size();
int columns = matrix[0].size();
long long one = 1;
for(int i = 0; i < rows; i++)
for(int j = 0; j < columns; j++){
row &= (matrix[i][j] == 0)?(~(one<<i)):(0xffffffffffffffff);
column &= (matrix[i][j] == 0)?(~(one<<j)):(0xffffffffffffffff);
}
for(int i = 0; i < rows; i++)
for(int j = 0; j < columns; j++){
if((row & (one<<i)) == 0){
for(int k = 0; k < columns; k++)
matrix[i][k] = 0;
}
if((column & (one<<j)) == 0){
for(int k = 0; k < rows; k++)
matrix[k][j] = 0;
}
row |= (one<<i);
column |= (one<<j);
}
}
};
但是很遗憾,上面使用long long的方法无法通过所有的例子,有两个例子的行数或者列数超过了64位,所以这个方法行不通。
继续该思路,使用bitset,可以通过,代码如下,使用的switch没用if是为了提高速度。:
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
if(matrix.size() == 0)return;
int line = matrix.size();
int row = matrix[0].size();
bitset<256> lines;
bitset<256> rows;
for(int i = 0; i < line; i++)
for(int j = 0; j < row; j++){
lines[i] = ((matrix[i][j] == 0 || lines[i]) ? 1 : 0);
rows[j] = ((matrix[i][j] == 0 || rows[j]) ? 1 : 0);
}
for(int i = 0; i < line; i++)
for(int j = 0; j < row; j++){
switch(lines[i]){
case 1:{
for(int k = 0; k < row; k++)
matrix[i][k] = 0;
lines[i] = 0;
break;
}
case 0 :{
break;
}
}
switch(rows[j]){
case 1:{
for(int k = 0; k < line; k++)
matrix[k][j] = 0;
rows[j] = 0;
break;
}
case 0:{
break;
}
}
}
}
};
下面的方法是完全不需要额外的空间,思路是用第一行存储各个列是否需要变为0;用第一列存储各个行是否需要变为0.比如matrix[5][4],matrix[0][0]-matrix[0][3]存储着四个列是否需要改为0,matrix[0][0]-matrix[4][0],存储各个行的信息。需要注意的是matrix[0][0],如果第一行有个元素(不是matrix[0][0])是0,那么第一行需要改为0,这个时候matrix[0][0]需要改为0,以代表第一行需要改为0,但是如果第一列没有元素是0,那么就会由于matrix[0][0] = 0而导致第一列也都改为了0.代码中用l(line的缩写)代表第一行是否需要改为0,用r代表第一列是否需要改为0.
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
if (matrix.size() == 0)return;
int line = matrix.size();
int row = matrix[0].size();
bool l = false, r = false;
for (int i = 0; i < line; i++)
for (int j = 0; j < row; j++){
l = (i == 0 && matrix[i][j] == 0 || l) ? true : false;
r = (j == 0 && matrix[i][j] == 0 || r) ? true : false;
matrix[i][0] = (matrix[i][j] == 0) ? 0 : matrix[i][0];
matrix[0][j] = (matrix[i][j] == 0) ? 0 : matrix[0][j];
}
for (int i = 1; i < line; i++){
switch (matrix[i][0]){
case 0:{
for (int k = 0; k < row; k++)
matrix[i][k] = 0;
break;
}
default:{
break;
}
}
}
for (int j = 1; j < row; j++){
switch (matrix[0][j]){
case 0:{
for (int k = 0; k < line; k++)
matrix[k][j] = 0;
break;
}
default:{
break;
}
}
}
if (l){
for (int k = 0; k < row; k++)
matrix[0][k] = 0;
}
if (r){
for (int k = 0; k < line; k++)
matrix[k][0] = 0;
}
}
};