
方法一:构建两个一维 boolean 类型的标记数组分别记录每一行和每一列是否有零出现。在遍历数组的时候,如果某个元素为 0 ,那么就将该元素所在的行和列所对应的标记数组的位置赋成 true。然后再遍历数组时,使用标记数组更新原数组即可。
代码如下:
class Solution {
public void setZeroes(int[][] matrix) {
boolean[] rows = new boolean[matrix.length];
boolean[] cols = new boolean[matrix[0].length];
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[0].length; j++){
if(matrix[i][j] == 0){
//该元素所在一整行都标记为true
rows[i] = true;
//该元素所在一整列都标记为true
cols[j] = true;
}
}
}
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[0].length; j++){
if(rows[i] == true || cols[j] == true){
matrix[i][j] = 0;
}
}
}
}
}
时间复杂度为 O(n * m) + O(n * m) = O(2n *m) -> 即 O(n*m),而空间复杂度为 O(n + m)。还可以继续优化使空间复杂度为 O(1),即题目中的原地算法。
方法二:可以用矩阵的第一行和第一列来代替方法一中创建的两个标记数组,使空间复杂度为 O(1)。这样一来,如何记录原数组的第一行和第一列被修改的元素呢?可以额外使用两个标记变量分别记录第一行和第一列中是否原本就包含数字 0 。
整体的思路是: 预处理两个标记变量 -> 解放第一行与第一列 -> 使用其它行与列来标记处理第一行与第一列 -> 返回来第一行和第一列去更新其它行和列 -> 使用两个标记变量来更新第一行与第一列
代码如下:
class Solution {
public void setZeroes(int[][] matrix) {
boolean flagCol0 = false;
boolean flagRow0 = false;
for(int i = 0; i < matrix.length; i++){
if(matrix[i][0] == 0){
flagCol0 = true;
}
}
for(int j = 0; j < matrix[0].length; j++){
if(matrix[0][j] == 0){
flagRow0 = true;
}
}
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[0].length; j++){
if(matrix[i][j] == 0){
//该元素所在一整行都标记为true
matrix[0][j] = 0;
//该元素所在一整列都标记为true
matrix[i][0] = 0;
}
}
}
for(int i = 1; i < matrix.length; i++){
for(int j = 1; j < matrix[0].length; j++){
if(matrix[0][j] == 0 || matrix[i][0] == 0){
matrix[i][j] = 0;
}
}
}
if(flagCol0){
for(int i = 0; i < matrix.length; i++){
matrix[i][0] = 0;
}
}
if(flagRow0){
for(int j = 0; j < matrix[0].length; j++){
matrix[0][j] = 0;
}
}
}
}
时间复杂度为 O(2n + 2m + 2n*m) -> O(n * m),空间复杂度为 O(1)。

No responses yet