题目
给定一个数组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]。不能使用除法。
解析
从题目中,可以观察到数组B中的元素B[i],其实就是A[0]到A[n-1]的乘积除以A[i];然而,题目中说明了不能使用除法。可能大多数人拿到这个题目第一个想法就是累乘,把n-1个数字相乘,但是这么的效率太低,时间复杂度为O(n^2)。
其实如果我们仔细观察B[i]的组成,不难发现一些规律,先让我们画一个表:
B[i] | 0 | 1 | 2 | 3 | 4 | … | n-3 | n-2 | n-1 |
---|---|---|---|---|---|---|---|---|---|
B[0] | 1 | A[1] | A[2] | A[3] | A[4] | … | A[n-3] | A[n-2] | A[n-1] |
B[1] | A[0] | 1 | A[2] | A[3] | A[4] | … | A[n-3] | A[n-2] | A[n-1] |
B[2] | A[0] | A[1] | 1 | A[3] | A[4] | … | A[n-3] | A[n-2] | A[n-1] |
B[3] | A[0] | A[1] | A[2] | 1 | A[4] | … | A[n-3] | A[n-2] | A[n-1] |
B[4] | A[0] | A[1] | A[2] | A[3] | 1 | … | A[n-3] | A[n-2] | A[n-1] |
B[…] | A[0] | A[1] | A[2] | A[3] | A[4] | … | A[n-3] | A[n-2] | A[n-1] |
B[n-3] | A[0] | A[1] | A[2] | A[3] | A[4] | … | 1 | A[n-2] | A[n-1] |
B[n-2] | A[0] | A[1] | A[2] | A[3] | A[4] | … | A[n-3] | 1 | A[n-1] |
B[n-1] | A[0] | A[1] | A[2] | A[3] | A[4] | … | A[n-3] | A[n-2] | 1 |
在表中1即表示A[i](因为A[i]不用乘)
首先,先让我们看1的左边,不难发现自上而下有C[i] =C[i-1]×A[i-1](假设C[i]=A[0]×A[1]×A[2]×…×A[i-1]) 同样在1的右边,自下而上有D[i] = D[i+1]×A[i+1](假设D[i]=A[i+1]×…×A[n-2]×A[n-1])
利用这两个公式,我们就可以通过两次遍历,一次自上而下算出左半边,再自下而上遍历乘上右半边
JAVA代码
public class MultiplyArray {
public static void main(String[] args) {
int[] a = {1,2,3,4,5};
int[] b = multiply(a);
for (int num: b) {
System.out.println(num);
}
}
public static int[] multiply(int[] A) {
int n = A.length;
if(n < 2)
return null;
int[] B = new int[n];
B[0] = 1 ;
for(int i = 1 ;i<n;i++)
B[i] = B[i-1]*A[i-1];
int right = 1;
for(int i = n-2;i>=0;i--) {
right = right * A[i + 1];
B[i] = B[i]*right;
}
return B;
}
}