题意:
一个m * n数组若一个数为0,则将其所在的行、列所有数都设置为0,要求使用In-Place 算法。
In-Place
在原数组空间进行操作,即使空间复杂度为O(1)。
思路1:空间复杂度O(mn)
void setZeroes(vector<vector<int>>& matrix) {//O(mn)
if (matrix.empty() || matrix[0].empty()) return;
int m = matrix.size(), n = matrix[0].size();
vector<pair<int, int>> zero;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (matrix[i][j] == 0)
zero.push_back(pair<int, int>(i, j));
for (auto z : zero) {
for (int i = 0; i < m; ++i) matrix[i][z.second] = 0;
for (int i = 0; i < n; ++i) matrix[z.first][i] = 0;
}
}
思路2: 空间复杂度O(m+n)
void setZeroes(vector<vector<int>>& matrix) {//O(m+n)
if (matrix.empty() || matrix[0].empty()) return;
int m = matrix.size(), n = matrix[0].size();
set<int> row, col;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (matrix[i][j] == 0) {
row.insert(i);
col.insert(j);
}
for (auto z : col)
for (int i = 0; i < m; ++i) matrix[i][z] = 0;
for (auto z : row)
for (int i = 0; i < n; ++i) matrix[z][i] = 0;
}
思路3:空间复杂度O(1),很慢很慢
- 先扫描第一行第一列,如果有0,则将各自的flag设置为true
- 然后扫描除去第一行第一列的整个数组,如果有0,则将对应的第一行和第一列的数字赋0
- 再次遍历除去第一行第一列的整个数组,如果对应的第一行和第一列的数字有一个为0,则将当前值赋0
- 最后根据第一行第一列的flag来更新第一行第一列
void setZeroes(vector<vector<int>>& matrix) {//O(1)?
if (matrix.empty() || matrix[0].empty()) return;
int m = matrix.size(), n = matrix[0].size();
int rowFlag = 0, colFlag = 0;
for(int i=0;i<m;++i)
if (matrix[i][0] == 0) {
colFlag = 1;
break;
}
for (int i = 0; i<n; ++i)
if (matrix[0][i] == 0) {
rowFlag = 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(colFlag)
for (int i = 0; i < m; ++i) matrix[i][0] = 0;
if(rowFlag)
for (int i = 0; i < n; ++i) matrix[0][i] = 0;
}