leetcode 链接:零矩阵
题目
编写一种算法,若 M × N 矩阵中某个元素为 0,则将其所在的行与列清零。
示例:
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
输入:
[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]
输出:
[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]
解答 & 代码
这里给出一种原地算法,既不需要额外的空间:即使用第 0 行和第 0 列作标记数组,即让第 0 行、第 0 列的元素分别代表该列、该行是否包含 0。如果第 0 行的第 col 个元素为 0,则代表第 col 列含 0,要被全部置 0;如果第 row 行的第 0 个元素为 0,则代表第 row 行含 0,要被全部置 0
- 首先分别遍历第 0 行、第 0 列的所有元素,确定第 0 行、第 0 列原本是否包含 0,分别用两个布尔变量
row0_cotain_0
、col0_contain_0
表示 - 修改标记数组:遍历除第 0 行、第 0 列外的所有元素,如果某个元素
matrix[row][col]
为 0,就将第 0 行、第 0 列对应元素即matrix[0][col]
、matrix[row][0]
置 0 - 利用标记数组将需要置零的行、列(出去标记数组即第 0 行、第 0 列外)都置零
根据两个布尔变量
row0_cotain_0
、col0_contain_0
决定是否要将 第 0 行、第 0 列置 0class Solution {//原地算法,不需要额外空间
public:
void setZeroes(vector<vector<int>>& matrix) {
int rows = matrix.size();
int cols = matrix[0].size();
int row0_cotain_0 = false; //原本的第0行是否包含0
int col0_contain_0 = false; //原本的第0列是否包含0
//遍历第0行元素,如果包含0,则将row0_contain_0置为true
for(int col = 0; col < cols; ++col)
{
if(matrix[0][col] == 0)
row0_cotain_0 = true;
}
//遍历第0列元素,如果包含0,则将col0_contain_0置为true
for(int row = 0; row < rows; ++row)
{
if(matrix[row][0] == 0)
col0_contain_0 = true;
}
//用第0行和第0列作为两个标记数组,遍历其余行列元素,如果某个元素为0,则该列的第0个元素置0,该行的第0个元素置0,作为标记
//实际上,如果某个元素为0,则最终该行、该列的所有元素都要置0,因此这一步不用担心修改了第0行、第0列的元素
for(int row = 1; row < rows; ++row)
{
for(int col = 1; col < cols; ++col)
{
if(matrix[row][col] == 0)
{
matrix[row][0] = 0;
matrix[0][col] = 0;
}
}
}
//根据第0行、第0列这两个标记数组,将矩阵中(出去第0行、第0列)需要置零的行、列置零
for(int row = 1; row < rows; ++row)
{
for(int col = 1; col < cols; ++col)
{
if(matrix[row][0] == 0 || matrix[0][col] == 0)
matrix[row][col] = 0;
}
}
//如果第0行原本就有0,则最后要将第0行元素全部置0
if(row0_cotain_0)
{
for(int col = 0; col < cols; ++col)
matrix[0][col] = 0;
}
//如果第0列原本就有0,则最后要将第0列元素全部置0
if(col0_contain_0)
{
for(int row = 0; row < rows; ++row)
matrix[row][0] = 0;
}
}
};
执行结果: ``` 执行结果:通过
执行用时:12 ms, 在所有 C++ 提交中击败了 87.06% 的用户 内存消耗:11.8 MB, 在所有 C++ 提交中击败了 76.22% 的用户 ```