面试题66:构建乘积数组

1、题目描述:

  给定一个数组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]。不能使用除法。

2、思路:

  这道题意思就是 B[i],其实就是A数组除了 A[i] 之外所有元素的乘积,题目已经限定了不能用除法,因此只能用乘法。有一个很显然的思路就是求 B[i],就按部就班的乘B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1],也就是说求 B[i] 的每个元素的时候都要从头到尾乘一遍,这种方法的时间复杂度显然是O(n^2),时间复杂度过大,肯定不是最终解法。

  最终的解法应该是将数组分成两部分,第一部分是C[i]=A[0]*A[1]*...*A[i-1],第二部分是D[i]=A[i+1]*...*A[n-1],即B[i]=C[i] x D[i],上一步骤之所以时间复杂度这么高,是因为在计算每一个元素的时候都要重复计算一次A数组的乘积。这时拆分成两个数组,很显然这两个数组都具备递推性质,即C[i]=C[i-1] x A[i-1],D[i]=D[i-1] x A[i+1],具备了递推性就说明我们可以保存所有的中间结果,不需要全部重复计算了。因此可在代码中,创建两个数组,分别保存C[i]、D[i]的所有元素。在计算B[i]的时候只需要取出即可。

3、代码:

public class Solution {
public int[] multiply(int[] A) {
        if (A == null || A.length <= 0) {
            return null;
        }
 
        int[] C = new int[A.length];
        C[0] = 1;
        for (int i = 1; i < C.length; i++) {
            C[i] = C[i - 1] * A[i - 1];
        }
 
        int[] D = new int[A.length];
        D[D.length - 1] = 1;
        for (int i = D.length - 2; i >= 0; i--) {
            D[i] = D[i + 1] * A[i + 1];
        }
 
        int[] result = new int[A.length];
        for (int i = 0; i < result.length; i++) {
            result[i] = C[i] * D[i];
        }
        return result;
    }
}
上一篇:linux过滤文本空行和注释


下一篇:USACO题解——Section 1.2——Greedy Gift Givers