题目:73. 矩阵置零
- 难度: 中等
- 题目:给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
提示:
解法
该题要求原地算法,意思就是直接就在原来的矩阵上修改数据(数据覆盖)。
我们可以用矩阵的第一行和第一列代替方法一中的两个标记数组,以达到 O(1) 的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 00。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含 00。
在实际代码中,我们首先预处理出两个标记变量,接着使用其他行与列去处理第一行与第一列,然后反过来使用第一行与第一列去更新其他行与列,最后使用两个标记变量更新第一行与第一列即可。
C++解法:
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size(); //矩阵的行数
int n = matrix[0].size(); //矩阵的列数
int flag_col0 = false,flag_row0 = false;
for(int i = 0;i < m;i++){
if(!matrix[i][0]){ //如果每一行的行首,存在一个0,就将行首有0的标记设为true
flag_col0 = true;
}
}
for(int j = 0;j < n;j++){
if(!matrix[0][j]){ //如果每一行的列首,存在一个0,就将列首有0的标记设为true
flag_row0 = true;
}
}
for(int i = 1;i < m;i++){
for(int j = 1;j < n;j++){
if(!matrix[i][j]){ //如果某个元素是0,就将该元素所在的行首元素和列首元素设为0
matrix[i][0] = matrix[0][j] = 0;
}
}
}
for(int i = 1;i < m;i++){
for(int j = 1;j < n;j++){
if(!matrix[i][0] || !matrix[0][j]){ //遍历矩阵(已经更新过行首和列首数据的矩阵),如果所在的行首或者列首为0,就将该元素设为0
matrix[i][j] = 0;
}
}
}
if(flag_col0){ //如果每一行的行首(即第一列),存在0,就将该列都设为0
for(int i= 0;i < m;i++){
matrix[i][0] = 0;
}
}
if(flag_row0){ //如果每一列的列首(即第一行),存在0,就将该行都设为0
for(int i = 0;i < n;i++){
matrix[0][i] = 0;
}
}
}
};
C#解法:
public class Solution {
public void SetZeroes(int[][] matrix) {
int m = matrix.Length;
int n = matrix[0].Length;
bool flag_col0 = false,flag_row0 = false;
for(int i = 0;i < m;i++){
if(matrix[i][0] == 0){
flag_col0 = true;
}
}
for(int i = 0;i < n;i++){
if(matrix[0][i] == 0){
flag_row0 = true;
}
}
for(int i = 1;i < m;i++){
for(int j = 1;j < n;j++){
if(matrix[i][j] == 0){
matrix[i][0] = matrix[0][j] = 0;
}
}
}
for(int i = 1;i < m;i++){
for(int j = 1;j < n;j++){
if(matrix[i][0] == 0 || matrix[0][j] == 0){
matrix[i][j] = 0;
}
}
}
if(flag_col0){
for(int i = 0;i < m;i++){
matrix[i][0] = 0;
}
}
if(flag_row0){
for(int i = 0;i < n;i++){
matrix[0][i] = 0;
}
}
}
}