
首先第一种方法:我们可以用两个boolean类型的数组来记录行和列是否存在0。然后去遍历所有元素时,碰到0时就将其对应的行和列的boolean类型数组对应位置置为true。再用for循环去遍历将有0的行和列全部置为0。
代码如下:
这种方法的时间复杂度很容易知道为O(m*n)
因为你额外的创建了两个boolean类型的数组,所以空间复杂度为O(m+n)的
java
class Solution {
public void setZeroes(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
boolean[] row = new boolean[m];
boolean[] col =new boolean[n];
for(int i = 0; i < m; i++){
for(int j = 0 ; j < n; j++){
if(matrix[i][j] == 0){
row[i] = col[j] = true;
}
}
}
for(int i = 0; i < m; i++){
for(int j = 0 ; j < n; j++){
if(row[i] || col[j]){
matrix[i][j] = 0;
}
}
}
}
}
下面为们来对其进行优化:
将空间复杂度优化为O(1)
我们可以参照EXCEL表格的思想,将行和列有没有0都汇集在第一行和第一列。比如说一个3*3的矩阵,中甲的位置为0,那么就将它左边第二行第一列的元素和第一行第二列置为0。
最后我们只需要遍历第一行和第一列就可以知道哪行和哪列需要被全部置为0了。但是这样做真的没问题吗?那第一行和第一列本来有没有0呢,有的话也需要全部置为0,没有的话只有个别位置置为0。那么我们在刚开始遍历的时候就要先判断第一行和第一列是否原来就有0,有的话在最后将其全部置为0。
代码如下:
java
class Solution {
public void setZeroes(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
// 记录第一行是否包含 0
boolean firstRowHasZero = false;
for (int x : matrix[0]) {
if (x == 0) {
firstRowHasZero = true;
break;
}
}
// 记录第一列是否包含 0
boolean firstColHasZero = false;
for (int i = 0; i < m; i++) {
if (matrix[i][0] == 0) {
firstColHasZero = true;
break;
}
}
// 用第一列 matrix[i][0] 保存 rowHasZero[i]
// 用第一行 matrix[0][j] 保存 colHasZero[j]
for (int i = 1; i < m; i++) { // 无需遍历第一行,如果 matrix[0][j] 本身是 0,那么相当于 colHasZero[j] 已经是 true
for (int j = 1; j < n; j++) { // 无需遍历第一列,如果 matrix[i][0] 本身是 0,那么相当于 rowHasZero[i] 已经是 true
if (matrix[i][j] == 0) {
matrix[i][0] = 0; // 相当于 rowHasZero[i] = true
matrix[0][j] = 0; // 相当于 colHasZero[j] = true
}
}
}
for (int i = 1; i < m; i++) { // 跳过第一行,留到最后修改
for (int j = 1; j < n; j++) { // 跳过第一列,留到最后修改
if (matrix[i][0] == 0 || matrix[0][j] == 0) { // i 行或 j 列有 0
matrix[i][j] = 0;
}
}
}
// 如果第一列一开始就包含 0,那么把第一列全变成 0
if (firstColHasZero) {
for (int[] row : matrix) {
row[0] = 0;
}
}
// 如果第一行一开始就包含 0,那么把第一行全变成 0
if (firstRowHasZero) {
Arrays.fill(matrix[0], 0);
}
}
}
其他更精简的代码可参考:
作者:灵茶山艾府