给定一个 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]]
解法一:
class Solution {
public:
// 这个函数用于将给定的矩阵中的所有零所在的行和列都设置为零
void setZeroes(vector<vector<int>>& matrix) {
// 获取矩阵的行数和列数
int rows = matrix.size();
int cols = matrix[0].size();
// 创建两个向量作为行和列的标志,初始化为false
vector<bool> row(rows, false);
vector<bool> col(cols, false);
// 遍历矩阵,如果找到零,则在相应的行和列标志中标记
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == 0) {
row[i] = true; // 标记第i行包含零
col[j] = true; // 标记第j列包含零
}
}
}
// 再次遍历矩阵,根据行和列标志将相应元素设置为零
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (row[i] || col[j]) {
matrix[i][j] = 0; // 如果第i行或第j列被标记,则该元素设置为零
}
}
}
}
};
这个函数的思路是遍历矩阵两次,第一次标记每一行和每一列是否包含零,第二次根据这些标记将对应位置的元素置为零。
具体步骤如下:
- 首先获取矩阵的行数和列数,分别保存在变量rows和cols中。
- 创建两个向量row和col作为行和列的标志,初始化为false。这两个向量的长度分别为rows和cols。
- 第一次遍历矩阵,对于每一个元素matrix[i][j],如果它的值为0,则在相应的行标志row[i]和列标志col[j]中标记为true,表示第i行或第j列包含零。
- 第二次遍历矩阵,对于每一个元素matrix[i][j],如果第i行或第j列的标志row[i]或col[j]为true,则将该元素设置为零。
- 最终,矩阵中所有零所在的行和列都被设置为零。
这种方法的时间复杂度为O(m*n),其中m和n分别为矩阵的行数和列数。空间复杂度为O(m+n),需要额外的row和col向量来保存行和列的标志位。
解法二:
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int rows=matrix.size(),colows=matrix[0].size();
bool falg_col0=false,falg_row0=false;
for(int i=0;i<rows;i++){
if(matrix[i][0]==0)
falg_col0=true;
}
for(int i=0;i<colows;i++){
if(matrix[0][i]==0)
falg_row0=true;
}
for(int i=1;i<rows;i++){
for(int j=1;j<colows;j++){
if(!matrix[i][j]){
matrix[i][0]=matrix[0][j]=0;
}
}
}
for(int i=1;i<rows;i++){
for(int j=1;j<colows;j++){
if(matrix[i][0]==0||matrix[0][j]==0)
matrix[i][j]=0;
}
}
if(falg_col0){
for(int i=0;i<rows;i++){
matrix[i][0]=0;
}
}
if(falg_row0){
for(int i=0;i<colows;i++){
matrix[0][i]=0;
}
}
}
};
这段代码使用了另一种优化的方法来解决问题。基本思路是利用矩阵的第一行和第一列作为标志位,用来记录每一行和每一列是否需要被置为零。具体步骤如下:
- 首先获取矩阵的行数和列数,分别保存在变量rows和colows中。
- 创建两个布尔变量falg_col0和falg_row0,用来标记第一列和第一行是否需要被置为零,初始值都为false。
- 遍历第一列,如果发现某个元素matrix[i][0]为零,则将falg_col0设置为true,表示第一列需要被置为零。
- 遍历第一行,如果发现某个元素matrix[0][i]为零,则将falg_row0设置为true,表示第一行需要被置为零。
- 从第二行和第二列开始,遍历整个矩阵。对于每个元素matrix[i][j],如果为零,则将对应的第一行元素matrix[i][0]和第一列元素matrix[0][j]设置为零,作为标志位。
- 再次遍历整个矩阵,对于每个元素matrix[i][j],如果对应的第一行元素matrix[i][0]或第一列元素matrix[0][j]为零,则将该元素设置为零。
- 最后,根据falg_col0和falg_row0的值,如果需要将第一列或第一行置为零,则遍历对应的行或列,将所有元素设置为零。
这种方法的时间复杂度为O(m*n),其中m和n分别为矩阵的行数和列数。只使用了两个额外的布尔变量,因此空间复杂度为O(1)。这是一种原地修改矩阵的优化方法,不需要额外的空间来保存标志位。
解法三:解法二优化版
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int rows = matrix.size(), cols = matrix[0].size();
bool flag_col0 = false;
for (int i = 0; i < rows; i++) {
if (!matrix[i][0])
flag_col0 = true;
for (int j = 1; j < cols; j++) {
if (!matrix[i][j]) {
matrix[i][0] = matrix[0][j] = 0;
}
}
}
for (int i = rows - 1; i >= 0; i--) {
for (int j = 1; j < cols; j++) {
if (!matrix[i][0] || !matrix[0][j])
matrix[i][j] = 0;
}
if (flag_col0) {
matrix[i][0] = 0;
}
}
}
};
这段代码使用了类似于前面的方法,但是稍微进行了一些优化。基本思路是:
- 首先获取矩阵的行数和列数,分别保存在变量rows和cols中。
- 创建一个布尔变量flag_col0,用来标记第一列是否需要被置为零,初始值为false。
- 遍历矩阵的每一行,从第一列开始。如果发现某个元素matrix[i][0]为零,则将flag_col0设置为true,表示第一列需要被置为零。
- 对于每个元素matrix[i][j],如果为零,则将对应的第一行元素matrix[i][0]和第一列元素matrix[0][j]设置为零,作为标志位。
- 再次遍历矩阵的每一行,从最后一列开始向前遍历。对于每个元素matrix[i][j],如果对应的第一行元素matrix[i][0]或第一列元素matrix[0][j]为零,则将该元素设置为零。
- 如果flag_col0为true,说明第一列需要被置为零,此时再遍历矩阵的每一行,将第一列元素都设置为零。
这种方法的时间复杂度为O(m*n),其中m和n分别为矩阵的行数和列数。空间复杂度为O(1),只使用了一个布尔变量来保存标志位。这种方法也是一种原地修改矩阵的优化方法,不需要额外的空间来保存标志位,并且减少了不必要的遍历。