题目描述
给定一个 m x n
的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用原地算法。
示例 1:
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]] 输出:[[1,0,1],[0,0,0],[1,0,1]]
示例 2:
输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]] 输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
提示:
m == matrix.length
n == matrix[0].length
1 <= m, n <= 200
-231 <= matrix[i][j] <= 231 - 1
进阶:
- 一个直观的解决方案是使用
O(mn)
的额外空间,但这并不是一个好的解决方案。 - 一个简单的改进方案是使用
O(m + n)
的额外空间,但这仍然不是最好的解决方案。 - 你能想出一个仅使用常量空间的解决方案吗?
解题思路
-
首先判断第一行和第一列是否需要置零:
- 检查第一行和第一列中是否有零,这将决定在最后是否需要将整个第一行或第一列置零。
-
使用矩阵的第一行和第一列来标记零元素:
- 从第二行和第二列开始,如果某个元素为零,就将对应的第一行和第一列的元素设置为零。这样,第一行和第一列就充当了标记的作用。
-
根据第一行和第一列的标记来置零相应的行和列:
- 再次遍历矩阵,从第二行和第二列开始,如果发现第一行或第一列的对应位置为零,则将当前元素置零。
-
根据一开始的检查结果,更新第一行和第一列:
- 如果第一行中原本有零,就将整个第一行置零。
- 如果第一列中原本有零,就将整个第一列置零。
代码实现(C++)
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
bool firstRowZero = false;
bool firstColZero = false;
int rows = matrix.size();
int cols = matrix[0].size();
// Determine if the first row or first column is zero
for (int i = 0; i < rows; i++) {
if (matrix[i][0] == 0) {
firstColZero = true;
break;
}
}
for (int j = 0; j < cols; j++) {
if (matrix[0][j] == 0) {
firstRowZero = true;
break;
}
}
// Use first row and first column as markers
for (int i = 1; i < rows; i++) {
for (int j = 1; j < cols; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
// Set zeroes for cells based on the markers
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;
}
}
}
// Finally set zeroes for first row and first column if needed
if (firstColZero) {
for (int i = 0; i < rows; i++) {
matrix[i][0] = 0;
}
}
if (firstRowZero) {
for (int j = 0; j < cols; j++) {
matrix[0][j] = 0;
}
}
}
};
复杂度分析
- 时间复杂度:O(m*n),其中 m 是行数,n 是列数。
- 空间复杂度:O(1),我们利用了矩阵的第一行和第一列来作为额外空间,不需要额外的存储空间。