题意:

一个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;

}