1.题目
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
2.示例
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]
输入: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]]
3.答案
不能一边遍历数组,一边在原数组上将 0 元素所在行和所在列全部变为0。.所以需要额外空间来记录0元素所在的行或者列。
①O(mn)额外空间
使用额外的数组保存更新后的数组元素。
void setZeroes(vector<vector<int>>& matrix) {
vector<vector<int> > res(matrix.begin(),matrix.end());
for(int i=0;i<matrix.size();i++){
for(int j=0;j<matrix[0].size();j++){
if(matrix[i][j]==0){
for(int p=0;p<matrix[0].size();p++) res[i][p]=0; //第i行
for(int p=0;p<matrix.size();p++) res[p][j]=0; //第j列
}
}
}
matrix.assign(res.begin(),res.end());
}
②O(m+n)额外空间
使用额外的两个一维数组数组集合保存0元素所在的行或列,然后进行更新。
void setZeroes(vector<vector<int>>& matrix) {
unordered_set<int> row; //出现0元素的行
unordered_set<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.insert(i);
col.insert(j);
}
}
for(int i:row){
for(int j=0;j<matrix[0].size();j++)
matrix[i][j]=0;
}
for(int i:col){
for(int j=0;j<matrix.size();j++)
matrix[j][i]=0;
}
}
void setZeroes(vector<vector<int>>& matrix) {
vector<int> row; //记录需要清零的行数
vector<int> col; //记录需要清零的列数
for(int i=0;i<matrix.size();i++){
for(int j=0;j<matrix[0].size();j++){
if(matrix[i][j]==0){
row.push_back(i); //此行需要清零
col.push_back(j); //此列需要清零
}
}
}
for(int i:row) {
for(int j=0;j<matrix[0].size();j++) matrix[i][j]=0;
}
for(int i:col){
for(int j=0;j<matrix.size();j++) matrix[j][i]=0;
}
}
③O(1)空间
刚好可以利用第一行和第一列作为两个一维数组标记0所在行或列,此时需要额外的标记记录第0行和第0列是否需要置零。
记录第0行和第0列的情况之后,继续遍历剩下的元素,将需要清零的行数保存到数组第0列,列数保存到数组第0行。
void setZeroes(vector<vector<int>>& matrix) {
// 使用数组的第一行和第一列保存要清零的列数和行数
//首先需要变量记录第0行和第0列是否需要清零
int row=0,col=0;
for(int i=0;i<matrix[0].size();i++)
if(matrix[0][i]==0) row=1; //第0行需要清零
for(int i=0;i<matrix.size();i++)
if(matrix[i][0]==0) col=1; //第0列需要清零
for(int i=1;i<matrix.size();i++){
for(int j=1;j<matrix[0].size();j++){
if(matrix[i][j]==0){
matrix[i][0]=0; //第i行需要清零
matrix[0][j]=0; //第j列需要清零
}
}
}
for(int i=1;i<matrix.size();i++){ //检查第1列有哪个位置标记为0
if(matrix[i][0]==0) { //第i行置零
for(int j=1;j<matrix[0].size();j++){
matrix[i][j]=0;
}
}
}
for(int j=1;j<matrix[0].size();j++){ //检查第1行有哪个位置标记为0
if(matrix[0][j]==0){ //第j列清零
for(int i=1;i<matrix.size();i++){
matrix[i][j]=0;
}
}
}
if(row) { //第0行置零
for(int i=0;i<matrix[0].size();i++) matrix[0][i]=0;
}
if(col){ //第0列置零
for(int i=0;i<matrix.size();i++) matrix[i][0]=0;
}
}