官解1: 使用第一行和第一列当作标记位
- 使用第一行和第一列当作标记位
- 另外用两个变量记录第一行第一列是否有0
java
class Solution {
public void setZeroes(int[][] matrix) {
if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return;
int m = matrix.length;
int n = matrix[0].length;
boolean row0 = false;
boolean col0 = false;
// 记录第一行第一列元素是否包含0(因为第一行第一列元素会被后续覆盖)
for(int i = 0; i<m;i++){
if(matrix[i][0] == 0) {
row0 = true;
break;
}
}
for(int j = 0; j<n;j++){
if(matrix[0][j] == 0) {
col0 = true;
break;
}
}
// 使用第一行第一列,标记从第二行第二列元素开始是否包含0
for(int i = 1;i<m;i++){
for(int j = 1;j<n ;j++){
if(matrix[i][j] == 0){
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
// 根据第一行、第一列的情况开始往矩阵中填充0
for(int i = 1;i<m;i++){
if(matrix[i][0] == 0){
for(int j = 1;j<n;j++) matrix[i][j] = 0;
}
}
for(int j = 1;j<n;j++){
if(matrix[0][j] == 0){
for(int i = 1;i<m;i++) matrix[i][j] = 0;
}
}
// 处理第一行、列
if(row0){
for(int i= 0;i<m;i++) matrix[i][0] = 0;
}
if(col0){
for(int j = 0;j<n;j++) matrix[0][j] = 0;
}
}
}
代码精简
这里:
java
// 根据第一行、第一列的情况开始往矩阵中填充0
for(int i = 1;i<m;i++){
if(matrix[i][0] == 0){
for(int j = 1;j<n;j++) matrix[i][j] = 0;
}
}
for(int j = 1;j<n;j++){
if(matrix[0][j] == 0){
for(int i = 1;i<m;i++) matrix[i][j] = 0;
}
}
也可以写成这样:
java
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;
}
}
}
官解2: 仅使用一个变量col0
这个理解起来有点困难。
- 循环置0时,从最后一行开始向前遍历:因为第一行是后面所有元素的标志位,如果先把第一行元素置0,后面所有元素都会变成0.
- 为什么需要且仅需要一个标志变量col0:对于第一列来说,它的元素被覆盖用作行标识,所以需要一个变量来记录是否需要清零;而对第一行来说,虽然它被当作列标识,但是matrix[0][0] 作为第一行是否需要清零的标志,因此不需要额外的row0.
java
class Solution {
public void setZeroes(int[][] matrix) {
if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return;
int m = matrix.length;
int n = matrix[0].length;
boolean col0 = false;
for(int i = 0; i<m;i++){
// 第一列为0
if(matrix[i][0] == 0) col0 = true;
for(int j = 1;j<n ;j++){
if(matrix[i][j] == 0){
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for(int i = m -1;i >= 0;i--){
for(int j = n-1;j >= 1;j--){
if( matrix[i][0] == 0 || matrix[0][j] == 0){
matrix[i][j] = 0;
}
}
if(col0){
matrix[i][0] = 0;
}
}
}
}