这个题目不难,看题目最后的说明,说可以用O(mn)空间来解决,也可以用O(m+n)空间来解决。说白了这个问题就是记录每行或每列是否有0的问题,有零则设置一个标志。那么O(mn)的不用说了,就是每个位置都记录,然后用记录的标志去更新原数组。接下来说一下O(m+n)的情况:
O(m+n)则是以行或者列为单位来记录,申请一个标志数组flag[rows+cols]
,遍历matrix的时候可以得到一个元素所在的行和列,然后将flag对应的位置设置为true,公式为flag[i] = true
和flag[rows + i] = true
。
在遍历flag从而更新原数组的时候,我们要分别更新每一行和每一列,因为我们的flag就是将行和列分开标记的,只是存在了一起。比如我们数组是3 * 3
,遍历到了flag[1] = true
,我们只能知道第二行包含0,但是它在第几列我们不知道,然后遍历到了flag[4] = flag[rows + 1] = true
,此时我们才知道第一列中也有0,所以进而更新第一列。代码如下:
public void setZeroes(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
boolean[] flag = new boolean[rows + cols];
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (matrix[i][j] == 0) {
flag[i] = true; //行标志
flag[rows+j] = true; //列标志
}
}
}
//根据flag来更新原数组
for (int i = 0; i < flag.length; ++i) {
if (i < rows && flag[i]) { //i < rows说明我们正在遍历行标志,只更新行
//先更新这一行中的每一列
for (int col = 0; col < cols; ++col)
matrix[i][col] = 0;
} else if (flag[i]) { // 否则我们在遍历列标志
//更新这一列的中每一行
for (int row = 0; row < rows; ++row)
matrix[row][i-rows] = 0;
}
}
}