我开始阅读着名的“破解编码面试”一书,我想做以下练习。
编写一个算法,使得如果MxN矩阵中的元素为0,则整个行和列都设置为0.
以下是作者的解决方案:
public static void setZeros(int[][] matrix) {
int[] row = new int[matrix.length];
int[] column = new int[matrix[0].length];
// Store the row and column index with value 0
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length;j++) {
if (matrix[i][j] == 0) {
row[i] = 1;
column[j] = 1;
}
}
}
// Set arr[i][j] to 0 if either row i or column j has a 0
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if ((row[i] == 1 || column[j] == 1)) {
matrix[i][j] = 0;
}
}
}
}
我同意作者的主要观点。我们不必在矩阵中存储'0'的位置,而只需要存储有关的行和列的位置。但是我在她的解决方案中发现有点“奇怪”的是,最后,她在矩阵的所有单元格上做了一个循环,这在我看来是不必要的。
这是我的解决方案:
static int[][] replaceMatrix(int[][] matrix){
int M = matrix.length;
int N = matrix[0].length;
boolean[] row = new boolean[M] ;
boolean[] column = new boolean[N];
for (int i =0; i< M; i++) {
for (int j = 0; j<N; j++ ){
if (matrix[i][j] == 0) {
row[i] = true;
column[j] = true;
}
}
}
for (int i =0; i<M; i++){
if (row[i]){
for (int k =0; k<N; k++){
matrix[i][k]=0;
}
}
}
for (int j =0; j<N; j++){
if (column[j]){
for (int k =0; k<M; k++){
matrix[k][j]=0;
}
}
}
我是编程新手,所以我不能完全确定这一点。但是在我的解决方案中,如果我们除了存储0位置的第一步之外,我的程序的第二部分的时间复杂度为O(M + N),而她的解决方案具有复杂性O(M * N)。
问题是一般复杂性是否相同O(M * N +(M + N))与复杂度O(2 * M * N)相同,不是吗? (我不完全确定)。 例如,如果它是M = N的矩阵,那么两个程序的两个复杂度将是O(M ^ 2)。
我真的想知道在这种情况下复杂性是否存在差异?
ps:我读过用位向量可以改善空间复杂度。但我真的不明白。你能给我一个关于它的一般概念(用Java)吗?
答案 0 :(得分:2)
最后两个for循环的时间复杂度仍为O(M * N),因为在最坏的情况下,for for循环将运行k次的最大值。
答案 1 :(得分:0)
你和作者的解决方案在技术上没有区别,因为你们两个都遍历了整个矩阵。如果我们必须考虑大O符号**两个代码都是相同的**
实际上作者的代码有点(一点点我不是指不同的时间复杂度)更好。原因如下:
假设在您的布尔行数组中,所有行都设置为true。然后在你的情况下,你将遍历所有行和每行的每个元素,这些元素基本上遍历整个矩阵。
假设在您的布尔列数组中,所有列都设置为true。然后在您的情况下,您将遍历所有列并遍历每列的每个元素,这些元素基本上遍历整个矩阵。
所以你实际上遍历整个矩阵两次。但是代码的时间复杂度是相同的,因为O(M * N)和O(2 * M * N)是相同的。
您已经完成了节省空间,因为您使用了布尔数据类型。