给定一个 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.lengthn == matrix[0].length1 <= m, n <= 200-231 <= matrix[i][j] <= 231 - 1
进阶:
- 一个直观的解决方案是使用
O(_m__n_)的额外空间,但这并不是一个好的解决方案。 - 一个简单的改进方案是使用
O(_m_ + _n_)的额外空间,但这仍然不是最好的解决方案。 - 你能想出一个仅使用常量空间的解决方案吗?
方法一:最暴力的解法(非原地)
直接遍历数组,遇到0就再分别遍历行和列。
问题:遇到0之后,将其所在行和列的所有元素都置0,后续遍历到"原本为1但被置0"的格子,会误判为该格子原本就是0,进而导致将该格子行列所在元素错误地置0
解决方法:使用一个flag数组记录matrix原本的模样,if条件中只需判断flag中该位置是否为0即可
代码:
java
class Solution {
public void setZeroes(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
int[][] flag = new int[row][];
for(int i=0;i<row;i++) {
flag[i] = matrix[i].clone();
}
for(int i=0;i<row;i++) {
for(int j=0;j<col;j++) {
if(flag[i][j] == 0) {
for(int m=0;m<col;m++) {
matrix[i][m] = 0;
}
for(int n=0;n<row;n++) {
matrix[n][j] = 0;
}
}
}
}
}
}
因为时间问题,就没写Go/Python/C++版本了,后续的文章主要都是Java/Go/Python版本
时间复杂度:
- 最好情况:矩阵全为1,O(mn)
- 最坏情况:矩阵全为0,O(mn(m+n))
- 其中m、n分别为矩阵的行数与列数
方法二:使用额外数组记录该行/列是否含0(非原地)
使用一个长为row的布尔数组 rowHasZero[] 记录第 i 行是否含0,如果含0,rowHasZero[i] = true
列同理
判断完行列是否含0后,再次遍历matrix,如果 rowHasZero/colHasZero 为true,就把该行/列的所有元素都置0
java
class Solution {
public void setZeroes(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
boolean rowHasZero[] = new boolean[row];
boolean colHasZero[] = new boolean[col];
for(int i=0;i<row;i++) {
for(int j=0;j<col;j++) {
if(matrix[i][j] == 0) {
rowHasZero[i] = true;
colHasZero[j] = true;
}
}
}
for(int i=0;i<row;i++) {
for(int j=0;j<col;j++) {
if(rowHasZero[i] || colHasZero[j]) {
matrix[i][j] = 0;
}
}
}
}
}
方法三:用行头/列头代替两个HasZero数组(原地)
如果这一行有0,那么标记行头为0,后续置0时通过行头即可判断是否要将该行全部置0,列同理
问题:
考虑第一行全为1,第一列含0的矩阵,例如:
1 1 1
1 1 1
0 1 1
行列判断完后,变为:
0 1 1
1 1 1
0 1 1
此时开始置0,会误判为第一行有0,因为(0,0)是第一行和第一列的交点,所以这个位置为0无法判断究竟是行要置0还是列要置0,因此第一行和第一列需要用两个单独的布尔变量去判断是否含0,最后再分别处理
java
class Solution {
public void setZeroes(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
//使用行头和列头记录是否含0
boolean firstRowHasZero = false;
boolean firstColHasZero = false;
for(int x : matrix[0]) {
if(x == 0) {
firstRowHasZero = true;
break;
}
}
for(int i=0;i<row;i++) {
if(matrix[i][0] == 0) {
firstColHasZero = true;
break;
}
}
for(int i=1;i<row;i++) {
for(int j=1;j<col;j++) {
if(matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for(int i=1;i<row;i++) {
for(int j=1;j<col;j++) {
if(matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
if(firstRowHasZero) {
Arrays.fill(matrix[0],0);
}
if(firstColHasZero) {
for(int[] r : matrix) {
r[0] = 0;
}
}
}
}
结语
本文含0量极高,那么以下cp中究竟谁是0呢?
千束 & 泷奈

伞哥 & 小肥宅

罗mio & 朱律叶

明日香 & 香织

彩叶 & 辉夜

小林 & 托尔

夏纪 & 优子
