【剑指Offer解法总结】面试题66:构建乘积数组
题目:
给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。
方法一:双层for循环
时间复杂度为O(n^2)
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int length=A.length;
int[] B=new int[length];
for(int i=0;i<length;i++){
B[i]=1;
for(int j=0;j<length;j++){
if(i==j){
B[i]*=1;
}else{
B[i]*=A[j];
}
}
}
return B;
}
}
方法二:矩阵上三角下三角乘积
B[i]的值可以看作下图的矩阵中每行的乘积。
下三角用连乘求得,上三角从下向上也是连乘。因此我们的思路就很清晰了,先算下三角中的连乘,再算上三角,最终将下三角与上三角相乘即可得到B[i]
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int length=A.length;
int[] B=new int[length];
//下三角
int[] C=new int[length];
//上三角
int[] D=new int[length];
//求下三角
C[0]=1;
for(int i=1;i<length;i++){
C[i]=C[i-1]*A[i-1];
}
//求上三角
D[length-1]=1;
for(int i=length-2;i>=0;i--){
D[i]=D[i+1]*A[i+1];
}
//求B[i]
for(int j=0;j<length;j++)
B[j]=C[j]*D[j];
return B;
}
}
该方法的时间复杂度为O(n),但是也占用了两个数组的空间。这种方法还可以改进,不占用两个数组的额外空间,因为下三角中的连乘,是B[i]中的一部分,我们可以先将B[i]赋值为下三角的连乘,然后倒过来(从后往前)按上三角中的连也乘进去。
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int length=A.length;
int[] B=new int[length];
B[0]=1;
for(int i=1;i<length;i++)
B[i]=B[i-1]*A[i-1];
int temp=1;
for(int j=length-2;j>=0;j--){
temp*=A[j+1];
B[j]*=temp;
}
return B;
}
}