问题描述
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.
Follow up:
Did you use extra space?
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?
问题分析
给定一个m*n的数组,如果有一个位置上为0。那么这一行和这一列都被标记为0.
这个时间复杂度一定是O(m*n).对于那一列和哪一行需要被标记为0,需要有额外的空间来记录这些数据。所以有两种方式其中空间复杂度是O(m+n).做法是使用两个数组,分别标记需要被设置为0的行和列。在标记结束的时候,将这些数据清楚。和jvm的标记清除算法有点像。
代码实现
public void setZeroes(int[][] matrix) {
//使用两个数组,分别是行和列来表示。
if (matrix == null || matrix.length == 0) {
return;
}
int row = matrix.length;
int col = matrix[0].length;
int[] rows = new int[row];
int[] cols = new int[col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (matrix[i][j] == 0) {
rows[i] = 1;
cols[j] = 1;
}
}
}
for (int i = 0; i < row; i++) {
if (rows[i] == 1) {
for (int j = 0; j < col; j++) {
matrix[i][j] = 0;
}
}
}
for (int i = 0; i < col; i++) {
if (cols[i] == 1) {
for (int j = 0; j < row; j++) {
matrix[j][i] = 0;
}
}
}
}
算法改进
如果将空间复杂度降到O(1)。这个时候就需要使用到当前数组中的空间了。可以使用第一行和第一列来进行标记需要清理的行和列。做法是首先准备两个空间为,这个两个位置主要是判断当前第一列和第一行是否需要被清楚。然后将所有需要进行清楚的数据记录在第一行和第一列中。接着根据第一行和第一列的数据来清除系统中的数据,最后根据标记位将第一行和第一列清楚。
public void setZeroes(int[][] matrix) {
if (matrix == null || matrix.length == 0) {
return;
}
int row = matrix.length;
int col = matrix[0].length;
boolean colDel = false;//第一列需要删除
boolean rowDel = false;//第一行删除
for (int i = 0; i < row; i++) {
if (matrix[i][0] == 0) {
colDel = true;
break;
}
}
for (int i = 0; i < col; i++) {
if (matrix[0][i] == 0) {
rowDel = true;
break;
}
}
for (int i = 1; i < row; i++) {
for (int j = 1; j < col; j++) {
if (matrix[i][j] == 0) {
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for (int i = 1; i < row; i++) {
if (matrix[i][0] == 0) {
for (int j = 1; j < col; j++) {
matrix[i][j] = 0;
}
}
}
for (int i = 1; i < col; i++) {
if (matrix[0][i] == 0) {
for (int j = 1; j < row; j++) {
matrix[j][i] = 0;
}
}
}
if (rowDel) {
for (int i = 0; i < col; i++) {
matrix[0][i] = 0;
}
}
if (colDel) {
for (int i = 0; i < row; i++) {
matrix[i][0] = 0;
}
}
}
总结
算法实现过程中可能有一些中间数据需要记录,可以使用系统中已经有的空间来记录中间数据来降低空间复杂。