cpp
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size(); //行数
int n = matrix[0].size(); //列数
vector<int>row(m),col(n);
for(int i = 0;i<m;i++){
for(int j = 0;j<n;j++){
if(matrix[i][j] == 0){
row[i] = col[j] = 1;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(row[i]==1 || col[j]==1){
matrix[i][j]=0;
}
}
}
}
};
这段代码解决的是"矩阵置零"问题:只要某个位置原本是 0,就把它所在的整行和整列全部变成 0。
比如:
matrix = {
{1, 1, 1},
{1, 0, 1},
{1, 1, 1}
};
中间的 matrix[1][1] = 0,所以第 1 行和第 1 列都要置零,最后变成:
{
{1, 0, 1},
{0, 0, 0},
{1, 0, 1}
}
代码先获取矩阵的行数和列数:
int m = matrix.size(); // 行数
int n = matrix[0].size(); // 列数
然后创建两个辅助数组:
vector<int> row(m), col(n);
它们初始都是 0。可以理解为:
row[i] = 1 → 第 i 行需要全部置零
col[j] = 1 → 第 j 列需要全部置零
接着第一次遍历矩阵:
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(matrix[i][j] == 0){
row[i] = col[j] = 1;
}
}
}
如果发现:
matrix[i][j] == 0
那么就记录:
row[i] = 1;
col[j] = 1;
例如:
matrix[1][1] == 0;
那么:
row = [0,1,0]
col = [0,1,0]
表示:
第 1 行需要变成 0
第 1 列需要变成 0
然后第二次遍历:
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(row[i] == 1 || col[j] == 1){
matrix[i][j] = 0;
}
}
}
只要当前位置满足:
row[i] == 1
说明这一整行应该置零;
或者:
col[j] == 1
说明这一整列应该置零。
因此:
if(row[i] == 1 || col[j] == 1)
使用的是 ||,也就是**"行需要置零或者列需要置零,只要满足一个条件就置零。"**
你可以把整道题直接记成:
第一遍不修改矩阵,只记录哪些行、哪些列出现了 0;第二遍根据记录,把对应行和列全部置 0。
这里之所以不能第一遍发现 0 就直接把整行整列改成 0,是因为新改出来的 0 会影响后续判断。例如原来:
1 1 1
1 0 1
1 1 1
如果边遍历边改,可能把"后来产生的 0"误认为是"原来就存在的 0",导致更多行列错误地被置零。
所以这个算法最关键的思想就是:
先记录,再修改。
时间复杂度是:
\ O(mn) \\
因为矩阵遍历了两遍;额外空间是:
\ O(m+n) \\
因为使用了 row 和 col 两个辅助数组。