构建乘积数组--java

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

解析:这道题,直观的解法是:设置一个循环(由0到n-1),计算B[i]时,忽略掉A[i]项,把数组A中的其他项全部相乘,即得到B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。这样,一次循环过后,就可以在没有除法的条件下,得到数组B中所有的值。那么,这种解法的时间复杂度和空间复杂度是多少呢?时间复杂度:由于循环由0~n-1,即o(n),在每次循环中,要执行n-1次乘法运算,所以这种解法的时间复杂度为o(n)*o(n-1)=o(n2);空间复杂度为o(1)。

  显然,上面这种解法的时间复杂度较高,那么有没有o(n)的解法呢?我们不妨分析一下上面这种解法的问题,从而找到可以优化的突破口。上面的复杂度由两部分组成,第一部分:循环由0~n-1,显然我们需要计算每一个B[i],不管怎样,我们都没办法去掉这样的基本循环,也就是说这一部分带来了时间复杂度o(n)不能再进行优化;第二部分:每一次计算B[i]都需要进行n-1次乘法,也即是需要计算n次n-1个数相乘,细心的人可以发现,这里面有很多的乘法是重复的,正是由于这部分重复的乘法计算造成我们的时间复杂度很高。那么,有没有办法只计算一次这样的n-1个数相乘呢?我们可以定义两个中间数组来存储已经计算过得乘法结果,这样,在进行下一个B[i]计算时,我们只需要完成一次乘法就可以得到B[i]的结果了。这样,时间复杂度就变成了o(1),整个算法时间复杂度就降成了o(n)。具体分析思路如下:

首先,我们可以将数组B表示成矩阵的形式如下:

 B[0]  1 A[1] A[2] ... A[n-2] A[n-1]
B[1] A[0] 1 A[2] ... A[n-2] A[n-1]
B[2] A[0] A[1] 1 ... A[n-2] A[n-1]
... ... ... ... 1 ... ...
B[n-2] A[0] A[1] A[2] ... 1 A[n-1]
B[n-1] A[0] A[1] A[2] ... A[n-2] 1

如上图所示,矩阵的每一行代表数组B的一个元素,从上往下,依次是B[0],B[1],...B[n-2],B[n-1]。那么,我们可以将每一个B[i]看成两部分,分别用C[i]和D[i]表示。其中C[i] = A[0]*A[1]*...*A[i-1],D[i] = A[i+1]*...*A[n-2]*A[n-1],这样,B[i]=C[i]*1*D[i]。也就是说,我们可以每次更新数组C[i]和D[i],即C[i]=C[i-1]*A[i-1]和D[i]=D[i+1]*A[i+1](需要说明的是,这里C[i]的更新是按照从前往后,而D[i]则是从后往前),从而为我们节省了大量的重复的乘法计算,使得时间复杂度降为o(n)。

int[] multiply(int[] A){
    if(A==null||A.length<=0)//边界条件,最好附带上
            return null;
    int n = A.length;
    int[] B = new int[n];
    B[0]=1;
    /*更新C[i],这里我们不另外定义数组,直接将C[i]的计算结果存储在B[i]中,
       这样,再将D[i]的结果直接乘以B[i](此时B[i]等于C[i]),就得到了最终
       的B[i],显然为我们又节省了不少空间存储。
    */
    for(int i=1;i<n;i++){
            B[i]=B[i-1]*A[i-1];
    }
    int temp =1;
    //更新D[i],这里要从n-2开始,因为B[n-1]已得到最终结果
    for(int j=n-2;j>=0;j--){
            temp*=A[j+1];
            B[j]*=temp;
    }   return B;
}

  显然,上述解法的时间复杂度为:2*o(n)*2=o(n)。

时间: 2024-08-02 20:22:39

构建乘积数组--java的相关文章

剑指offer-66 构建乘积数组

剑指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].不能使用除法.(注意:规定B[0] = A[1] * A[2] * ... * A[n-1],B[n-1] = A[0] * A[1] * ... * A[n-2];) 思路: 自己解答: import java.util.ArrayList; public class So

剑指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].不能使用除法. 问题分析 如果没有不能使用除法的限制,可以用公式B[i]=A[0]*A[1]*.....*A[n-1]/A[i]表示,使用除法时要特别注意A[i]等于0的情况. 因为每个B[i]都会有重复,其中有着一定的规律性,我们可以尝试找规律,利用规律来解答这道问题. B

《剑指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].不能使用除法. #include <cstdio> #include <vector> using namespace std; //把B[i]看成[=A[0],A[1],… ,A[i-1],1,A[i+1],…,A[n-1]] //对于B,就成

剑指offer:构建乘积数组

http://www.cnblogs.com/wxdjss/p/5448990.html 给定一个数组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].不能使用除法. 不乘第i个数 可以把B[i]=A[0]*A[1]*.....*A[i-1]*A[i+1]*.....*A[n-1].看成A[0]*A[1]*.....*A[i-1]和 A[i+1]*.....A[n-2]*

52、构建乘积数组

题目:给定一个数组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[i] = c[i]* d[i] //c[i] = A[0]*A[1]*...*A[i-1] = C[i-1] * A[i-1]; //D[I] = A[i-1]*A[i+1]*...*A[n-1] = a[i+1]*D[I+1]; 注意: 用一个变量B[]表示,C和D im

《剑指offer》构建乘积数组

[ 声明:版权所有,转载请标明出处,请勿用于商业用途.  联系信箱:[email protected]] 题目链接:http://www.nowcoder.com/practice/94a4d381a68b47b7a8bed86f2975db46?rp=3&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 题目描述 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中

51、构建乘积数组

一.题目 给定一个数组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].不能使用除法. 二.解法 1 import java.util.ArrayList; 2 public class Solution { 3 public int[] multiply(int[] A) { 4 int len = A.length; 5 int[] B = new int[len];

(剑指Offer)面试题52:构建乘积数组

题目: 给定一个数组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].不能使用除法. 思路: 方法1: 直接连乘n-1个数,得到B[i]: 时间复杂度:O(n^2) 方法2: 构建前向乘积数组C[i]=A[0]*A[1]*...*A[i-1],即C[i]=C[i-1]*A[i-1]: 构建后向乘积数组D[i]=A[n-1]*A[n-2]*...A[n-i+1],即D[i]

剑指offer(二十九)之构建乘积数组

题目描述 给定一个数组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循环,当i=j时,不做处理,否则进行累乘.代码简单,一看就懂. 代码: <span style="font-family:SimSun;font-size:18px;">import java.util.ArrayList; public