题目
给定一个 m×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]]
题解
为了使用原地算法解决这个问题,我们可以利用矩阵的第一行和第一列来记录需要置零的行和列。这样可以避免使用额外的空间。具体步骤如下:
-
检查第一行和第一列是否有零:
- 分别检查第一行和第一列是否有零,并用
firstRowZero
和firstColZero
记录结果。
- 分别检查第一行和第一列是否有零,并用
-
使用第一行和第一列记录需要置零的行和列:
- 遍历矩阵的其他元素(不包括第一行和第一列),如果元素为零,则将对应的第一行和第一列的元素设为零。
-
置零对应的行和列:
- 根据第一行和第一列的记录,置零对应的行和列。
-
处理第一行和第一列:
- 最后根据
firstRowZero
和firstColZero
的记录,处理第一行和第一列。
- 最后根据
代码实现
以下是实现原地置零的代码:
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int rows = matrix.size(), cols = matrix[0].size();
bool firstRowZero = false, firstColZero = false;
// 检查第一行是否有零
for (int j = 0; j < cols; ++j) {
if (matrix[0][j] == 0) {
firstRowZero = true;
break;
}
}
// 检查第一列是否有零
for (int i = 0; i < rows; ++i) {
if (matrix[i][0] == 0) {
firstColZero = true;
break;
}
}
// 使用第一行和第一列记录需要置零的行和列
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;
}
}
}
// 置零对应的行和列
for (int i = 1; i < rows; ++i) {
if (matrix[i][0] == 0) {
for (int j = 1; j < cols; ++j) {
matrix[i][j] = 0;
}
}
}
for (int j = 1; j < cols; ++j) {
if (matrix[0][j] == 0) {
for (int i = 1; i < rows; ++i) {
matrix[i][j] = 0;
}
}
}
// 最后处理第一行和第一列
if (firstRowZero) {
for (int j = 0; j < cols; ++j) {
matrix[0][j] = 0;
}
}
if (firstColZero) {
for (int i = 0; i < rows; ++i) {
matrix[i][0] = 0;
}
}
}
};
详细解题思路
-
检查第一行和第一列是否有零:
- 遍历第一行和第一列,如果发现零元素,将
firstRowZero
或firstColZero
设为true
。
- 遍历第一行和第一列,如果发现零元素,将
-
使用第一行和第一列记录需要置零的行和列:
- 遍历矩阵的其他部分(从第二行第二列开始),如果发现零元素,将对应的第一行和第一列的元素设为零。
-
置零对应的行和列:
- 根据第一行和第一列的标记,遍历矩阵的其他部分,将需要置零的行和列的元素设为零。
-
处理第一行和第一列:
- 根据
firstRowZero
和firstColZero
的标记,最后处理第一行和第一列,将其元素设为零。
- 根据
这种方法有效地避免了额外空间的使用,实现了原地操作。
希望这个博客能帮助你理解如何使用原地算法将矩阵中包含 0 的行和列的所有元素设为 0。如果你有任何问题或需要进一步的解释,请随时提问!