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:新建一个同样大小数组,先扫描行,若某行存在零元素,则整行清零;再扫描列,若某列存在零元素,则整列清零。最后将其赋给原矩阵。空间复杂度O(mn)。
class Solution { public: void setZeroes(vector<vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) return; int m = matrix.size(); int n = matrix[0].size(); vector< vector<int> > tmpMat; for (int i = 0; i < m; i++) { tmpMat.push_back(matrix[i]); if (find(matrix[i].begin(), matrix[i].end(), 0) != matrix[i].end()) tmpMat[i].assign(n, 0); } for (int j = 0; j < n; j++) { for (int i = 0; i < m; i++) { if (matrix[i][j] == 0) { for (int k = 0; k < m; k++) tmpMat[k][j] = 0; break; } } } for (int i = 0; i < m; i++) copy(tmpMat[i].begin(), tmpMat[i].end(), matrix[i].begin()); } };
解法2:新建一个数组,用来存储矩阵中所有零元素的位置。然后再扫描一遍矩阵,将零元素所在的行列清零即可。空间复杂度O(m+n)。
class Solution { public: void setZeroes(vector<vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) return; int m = matrix.size(); int n = matrix[0].size(); vector< pair<int, int> > zeroIndex; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] == 0) zeroIndex.push_back(make_pair(i, j)); } } for (int i = 0; i < zeroIndex.size(); i++) { for (int j = 0; j < n; j++) matrix[zeroIndex[i].first][j] = 0; for (int k = 0; k < m; k++) matrix[k][zeroIndex[i].second] = 0; } } };
解法3:解法2中zeroIndex所用空间可以用原矩阵中某个零元素所在的行和列来代替,这样可以使得空间复杂度下降为O(1)。不需要将所有零元素的位置存下来。对于两个零元素坐标(i,j)和(k,l),如果i!=k&&k!=l,则需要将两者均存储下来,否则如果有i=k(或者j=l),则这两个零元素对矩阵行(或者列)的清零效果是一样的,只需要存储其中的一个(i或者k)(或者 j或者l)即可,而j和l(或者i和k)则必须分开存储。步骤:
- 先扫描第一行第一列,如果有0,则将各自的flag设置为true
- 然后扫描除去第一行第一列的整个数组,如果有0,则将对应的第一行和第一列的数字赋0
- 再次遍历除去第一行第一列的整个数组,如果对应的第一行和第一列的数字有一个为0,则将当前值赋0
- 最后根据第一行第一列的flag来更新第一行第一列
class Solution { public: void setZeroes(vector<vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) return; int m = matrix.size(); int n = matrix[0].size(); bool rh0 = false, ch0 = false; //标识第一行和第一列是否存在0 for (int i = 0; i < n && !rh0; i++) rh0 = matrix[0][i] == 0 ? true : rh0; for (int i = 0; i < m && !ch0; i++) ch0 = matrix[i][0] == 0 ? true : ch0; for (int i = 1; i < m; i++) //对除去原矩阵的第一行和第一列得到的新矩阵扫描,标记0的位置 { 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 (rh0) matrix[0].assign(n, 0); if (ch0) { for (int i = 0; i < m; i++) matrix[i][0] = 0; } } };