73. 矩阵置零 - 力扣(LeetCode)
一、题目要求
给定一个 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)
的额外空间,但这仍然不是最好的解决方案。 - 你能想出一个仅使用常量空间的解决方案吗?
摘自LeetCode
二、解法1-暴力破解 O(N^3) 执行时间一般,内存消耗大
用一个 vv 保存matrix 的原始状态,然后遍历 vv;
当遍历到0时,让它的横竖都变成0,即:横不变,竖从上到下置0;竖不变,横从左到右置0
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
vector<vector<int>> vv = matrix;
for (int i = 0; i < matrix[0].size(); i++)
{
for (int j = 0; j < matrix.size(); j++)
{
if (vv[j][i] == 0)
{
for (int x = 0; x < matrix[0].size(); x++)
{
matrix[j][x] = 0;
}
for (int y = 0; y < matrix.size(); y++)
{
matrix[y][i] = 0;
}
}
}
}
}
};
二、解法2-标记数组 O(M*N)
创建两个标记数组 row 和 col;
遍历 matrix ,如果为0就记录它的行与列;
最后根据row中的行号置0,col中的列号置0
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
vector<int> row; // 标记哪一行有0
vector<int> col; // 标记哪一列有0
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[0].size(); j++)
{
if(matrix[i][j] == 0)
{
row.emplace_back(i);
col.emplace_back(j);
}
}
}
for(const auto& r:row) // 行置0
{
for(int x = 0;x < matrix[0].size();x++)
{
matrix[r][x] = 0;
}
}
for(const auto& c:col) // 列置0
{
for(int y = 0;y < matrix.size();y++)
{
matrix[y][c] = 0;
}
}
}
};
三、解法3-两个标记变量 O(M*N) 内存消耗低为O(1)
这是解法2的空间优化版,只用两个变量标记第一行、第一列是否要置0;
然后后遍历数组,如果有0就使第一行、第一列对应的下标标记为0(第一行、第一列对应下标本来就需要为0);
然后根据第一行、列的情况决定本行、列是否要置0;
最后根据两个标记变量决定第一行、列是否要全置0。
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int first_row = 1; // 标记第一行是否原本有0
int first_col = 1; // 标记第一列是否原本有0
for (const auto& num : matrix[0]) {
if (num == 0)
first_row = 0;
}
for (const auto& arr : matrix) {
if (arr[0] == 0)
first_col = 0;
}
for (int i = 1; i < matrix.size(); i++) { // 第一行、第一列分别标记本列、本行是否有0
for (int j = 1; j < matrix[0].size(); j++) {
if (matrix[i][j] == 0) {
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for (int i = 1; i < matrix[0].size(); i++) { // 列置0
if (matrix[0][i] == 0) {
for (int j = 1; j < matrix.size(); j++) {
matrix[j][i] = 0;
}
}
}
for (int j = 1; j < matrix.size(); j++) { // 行置0
if (matrix[j][0] == 0) {
for (int i = 1; i < matrix[0].size(); i++) {
matrix[j][i] = 0;
}
}
}
if (first_row == 0) // 根据标记处理第一行
for (auto& num : matrix[0])
num = 0;
if (first_col == 0) // 根据标记处理第一列
for (auto& num : matrix)
num[0] = 0;
}
};