Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.
给定一个m*n的举证,如果某一个元素为0,把它所在的行和列全部设置为0,并且在原矩阵上修改
Example 1:
Input:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
Output:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
Example 2:
Input:
[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]
Output:
[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]
Follow up:
A straight forward solution using O(mn) space is probably a bad idea.
A simple improvement uses O(m + n) space, but still not the best solution.
Could you devise a constant space solution?
解
问题其实很简单,主要考虑到有一个因素就是,不能在第一次遍历确定那些行列需要设置为0的时候就设置为0,这样会导致后面的遍历扫描到0不知道是被设置的还是原始输入。另外题目要求必须使用原始矩阵不能额外设置一个矩阵。
方案就是:
- 将要设置为0的行和列存在一个单独数据结构,
Set
或者用boolean[]
表示均可 - 为了减少内存占用,使用每一行和每一列的第一个元素表示这一行或者这一列是否需要置为0;需要考虑的就是(0,0)号元素因为既可以表示第一行也可以表示第一列,所以需要有一个定义,这个元素到底表示行还是列,然后另一个用一个单独变量保存。
public static void setZeroes(int[][] matrix) {
// 获得行数n和列数m
int n = matrix.length;
int m = matrix[0].length;
// 用于记录第一列是否为0
boolean isColumn = false;
// 第一遍遍历,找到那些行和列需要标记为0,用每一行和每一列的第一个元素设置为0表示他们这行或者列需要标记为0
// 由于第一行第一列的元素总是会优先于其他元素被遍历到,所以如果被set为0,不会对后续的遍历干扰,因为肯定已经遍历过
for (int i = 0; i < n; i++) {
// 由于matrix[0][0]元素既是第一列的第一个元素,也是第一行的第一个元素,所以需要区分一下
// 这里用matrix[0][0]表示第一行是否需要置为0,则第一列需不需要置为0需要一个单独元素来判断
// 就是上面指定的isColumn
// 所以每一行的遍历都要判断第一个元素是否为0,为0则标记第一列需要为0
// 并且由于第一个元素为0了,那么这一行相当于已经标记为要显示为0,就不需要额外标记了
// 如果是一行中第一个元素,那么说明第一列也需要标记为0,但是我们将第一行第一列的元素认为表示的是行
// 所以如果是一行中第一个元素,就需要额外记录下这一列需要标记为0
isColumn = isColumn?isColumn:matrix[i][0] == 0;
//如果直接从i,0开始判断,会将0,0元素设置为0,而实际上一行里面第一个元素为0的时候只表示这一行和第一列为0
//如果误将0,0元素设置为0,那么后面的遍历会误以为第一行也要为0,
//所以第一列都要单独判断
for (int j = 1; j < m; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
// 第二遍遍历,将除了第一行第一列以外的所有元素,根据第一行第一列的标记,判断是否置为0
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
// 如果第一个元素为0,表示第一行要标记为0
if (matrix[0][0] == 0) {
for (int j = 1; j < m; j++) {
matrix[0][j] = 0;
}
}
// 如果标记了第一列需要为0,就设置第一列为0
if (isColumn) {
//从第一行起,每一行第一个元素设置为0
for (int i = 0; i < n; i++) {
matrix[i][0] = 0;
}
}
for(int[] row:matrix) {
System.out.println(Arrays.toString(row));
}
}