首页 > 试题广场 >

构建乘积数组

[编程题]构建乘积数组
  • 热度指数:311813 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
给定一个数组 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](除 A[i] 以外的全部元素的的乘积)。程序中不能使用除法。(注意:规定 B[0] = A[1] * A[2] * ... * A[n-1],B[n-1] = A[0] * A[1] * ... * A[n-2])
对于 A 长度为 1 的情况,B 无意义,故而无法构建,用例中不包括这种情况。

数据范围: ,数组中元素满足
示例1

输入

[1,2,3,4,5]

输出

[120,60,40,30,24]
示例2

输入

[100,50]

输出

[50,100]
推荐
<分析>:
解释下代码,设有数组大小为5。
对于第一个for循环
第一步:b[0] = 1;
第二步:b[1] = b[0] * a[0] = a[0]
第三步:b[2] = b[1] * a[1] = a[0] * a[1];
第四步:b[3] = b[2] * a[2] = a[0] * a[1] * a[2];
第五步:b[4] = b[3] * a[3] = a[0] * a[1] * a[2] * a[3];
然后对于第二个for循环
第一步
temp *= a[4] = a[4];  
b[3] = b[3] * temp = a[0] * a[1] * a[2] * a[4];
第二步
temp *= a[3] = a[4] * a[3];
b[2] = b[2] * temp = a[0] * a[1] * a[4] * a[3];
第三步
temp *= a[2] = a[4] * a[3] * a[2];  
b[1] = b[1] * temp = a[0] * a[4] * a[3] * a[2];
第四步
temp *= a[1] = a[4] * a[3] * a[2] * a[1];  
b[0] = b[0] * temp = a[4] * a[3] * a[2] * a[1];
由此可以看出从b[4]到b[0]均已经得到正确计算。
class Solution {
public:
  vector<int> multiply(const vector<int>& A) {
  vector<int> vec;
  int sz=A.size();
  if(sz==0)
   return vec;
  vec.push_back(1);
  for(int i=0;i<sz-1;i++)
   vec.push_back(vec.back()*A[i]);
  int tmp=1;
  for(int i=sz-1;i>=0;i--)
  {
   vec[i]=vec[i]*tmp;
   tmp=tmp*A[i];
  }
  return vec;
    }
};

编辑于 2015-08-25 11:17:49 回复(54)
import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        int[] res = new int[A.length];
        for (int i=0;i<A.length;i++){
            int sum = 1;
            int pre = 0;
            while(pre<A.length){
                if(pre==i){
                    pre++;
                    continue;
                }
                 sum *= A[pre];
                 pre++;
            }
           res[i]=sum;
        }
        return res;
    }
}

发表于 2022-11-24 15:56:37 回复(0)
import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        int[] B=new int[A.length];
        for(int i=0;i<B.length;i++){
            B[i]=1;
            for(int j=0;j<i;j++){
                B[i]=A[j]*B[i];
            }
            for(int j=i+1;j<B.length;j++){
                B[i]=A[j]*B[i];
            }
        }
        return B;
    }
}
发表于 2022-06-06 09:33:20 回复(0)
实际上可以这么想 如果我们只是去每一个每一个的去遍历的话 时间复杂度为n的平方
如果想对所有数组进行相乘 然后每一个相除的话 又会出现两个问题 1 不能用除法 2 在其中会出现0这个元素 
因此牛客网官方解答的思想就是 我们在第一次遍历的时候 对于B数组的每一个元素 我们只把其乘积定到这个元素的上一个元素 就停止
第二次遍历的时候 跟第一次遍历思想一样 我们对B数组的每一个元素乘系数的时候 只乘其当前元素的后面部分 这样用两次循环就能解决问题了
public class Solution {
    public int[] multiply(int[] A) {
       // 这种最核心的实际上就是 点到位置 第一次遍历 就是成绩到其当前位置的前一个位置 
       // 第二次遍历也是从后往前进行遍历 最终也遍历到相同的感觉了为止
        // 牛 实际上自己也想过这样的情况 但实际上这样的一个操作 应该自己也应该细细感悟一下
       int[] B = new int[A.length];
       B[0] = 1;
       for(int i=1;i<=A.length-1;i++){
           B[i] = B[i-1]*A[i-1];
       }
       int temp = 1;
       for(int i=A.length-1;i>=0;i--){
           B[i] = B[i]*temp;
           temp = temp*A[i];
       }
       return B; 
    }
}
发表于 2022-05-21 21:31:23 回复(0)
import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        int[] dp1 = new int[A.length];
        int[] dp2 = new int[A.length];
        int[] res = new int[A.length];
        //动态规划 前后两次 便于理解
        dp1[0]=1;
        dp1[1]=A[0];
        dp2[A.length-1]=1;
        dp2[A.length-2]=A[A.length-1];
        for(int i=2;i<A.length;i++){
            dp1[i]=dp1[i-1]*A[i-1];
        }
        for(int i=A.length-3;i>=0;i--){
            dp2[i]=dp2[i+1]*A[i+1];
        }
        for(int i=0;i<A.length;i++){
            res[i]=dp1[i]*dp2[i];
        }
        return res;
    }
}

发表于 2022-04-25 18:29:41 回复(0)
import java.util.ArrayList;
public class Solution {
// 简单暴力
    public int[] multiply(int[] A) {
        int[] res = new int[A.length];
        for(int i =0; i < A.length; i++){
            int sum = 1;
            for(int j = 0; j < A.length; j++){
                if(j==i)
                    continue;
                sum*=A[j];
            }
            res[i] = sum;
        }
        return  res;

    }
}

发表于 2022-03-11 11:38:07 回复(0)
public class Solution {
    // 简单粗暴 使用前缀和数组
    public int[] multiply(int[] A) {
        if (A.length == 1) return A;
        int[] help = new int[A.length];
        int val = 1;
        for (int i = 0; i < A.length; i++) {
            help[i] = val;
            val *= A[i];
        }
        val = 1;
        for (int i = A.length-1; i >=0; i--) {
            help[i] *= val;
            val *= A[i];
        }
        return help;
    }
}

发表于 2022-01-25 11:33:20 回复(0)
import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        // 解法2:官方解法
        // 分2次for循环,先计算下三角,再计算上三角
        
        int ret[] = new int[A.length];
        // 下三角:正序乘
        ret[0]=1;
        for(int i=1;i<A.length;i++){
            ret[i] = ret[i-1] * A[i-1];
        }
        // 上三角:倒序乘
        int product = 1;
        for(int i=A.length-2;i>=0;i--){
            product *= A[i+1]; 
            ret[i] *= product;
        }
        
        return ret;
    }
}

发表于 2022-01-24 20:09:06 回复(0)
import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        if (A.length == 1)
            return new int[0];
        int[] B = new int[A.length];
        //创建数组
        for (int i = 0; i < B.length; i++)
            B[i] = 1;
        //先搞定i左边部分乘积
        for (int i = 1; i < B.length; i++)
            B[i] = B[i-1] * A[i-1];
        int mult = 1;
        //再搞定i右边部分乘积
        for (int i = B.length-2; i >= 0; i--) {
            mult *= A[i+1];
            B[i] *= mult;
        }
        return B;
    }
}

发表于 2022-01-10 19:50:34 回复(0)
        public int[] multiply(int[] A) {
        int B[] = new int[A.length];
        for(int i = 0 ; i < B.length; i ++){
            int sum = 1; // 用于记录乘积
            int j = 0;   //用于判断下标等当前下标
            while(j < A.length){
                if(j != i){
                   sum = sum * A[j];
                }
                j ++;
            }
            //循环结束后,对乘积存储到B数组中
            B[i] = sum;
        }
        return B;
    }

发表于 2022-01-09 18:28:23 回复(0)
这样不好吗?


import java.util.ArrayList;
import java.util.*;

public class Solution {
    public int[] multiply(int[] A) {
        int[] res = new int[A.length];
        Set<Integer> zeroSet = new HashSet<>();
        
        int sum = 1;
        
        for(int i = 0; i < A.length; i++){
            if(A[i] == 0){
                zeroSet.add(i);
                A[i] = 1;
            }
            sum *= A[i];
        }
        
       
        for(int i = 0; i < A.length; i++){
            if(zeroSet.size() == 0){
                res[i] = sum / A[i];
            }else if(zeroSet.contains(i) && zeroSet.size() == 1){
                res[i] = sum / A[i];
            }else {
                 res[i] = 0;
            }
           
        }
        
        return res;
    }
}
发表于 2022-01-08 19:40:02 回复(0)
import java.util.ArrayList;
import java.util.List;
public class Solution {
     public  int[] multiply(int[] A) {
        int[] res = new int[A.length];
        int index=0;
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < A.length; i++) {
            list.add(A[i]);
        }
        for (int i = 0; i < list.size(); i++) {
            List<Integer> list1 = new ArrayList<Integer>();
           list1.addAll(list);
            res[index++]=cal(list1,i);
        }

        return res;
    }
    public  int cal(List<Integer> list,int j){
        Integer remove = list.remove(j);

        int res=1;
        for (int i = 0; i < list.size(); i++) {
            res=res*list.get(i);
        }
        return  res;
    
    }
}
//比较笨的包里解决
发表于 2022-01-04 14:29:40 回复(0)
import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        int lengthA = A.length;
        int[] B = new int[lengthA];
        for (int i = 0; i < lengthA; i++){
            B[i] = 1;
        }
        for (int i = 1; i < lengthA; i++){
            B[i] = B[i-1]*A[i-1];
        }
        int temp = 1;
        for (int j = lengthA - 2; j >= 0; j--){
            temp = temp*A[j+1];
            B[j] = B[j]*temp;
        }
        return B;
    }
}

发表于 2021-12-15 17:14:14 回复(0)
类比于剑指Offer的解法
优化了某些不必要的步骤
核心思想就是计算A到底有几个值为0的元素,如果有两个,那返回的ret全部必为0
如果只有一位,把下标记录下来,再单独进行赋值即可
时间复杂度总体来说O(N),空间复杂度的话,也是O(1)
import java.util.ArrayList;
public class Solution {

    public int[] multiply(int[] A) {
        int[] ret = new int[A.length];
        if(A.length ==0){
            return null;
        }
        int sum = 1;
        int count =0;
        int flag = -1;
        boolean flag1 = false;
        for (int i = 0; i < ret.length; i++) {
            if(A[i] ==0){
                count++;
            }
            if(count ==1 & !flag1){
                flag = i;
                flag1 = true;
            }
            sum*=A[i];
            if(count==2){
                return ret;
            }
        }
        if(count ==1){
            for (int i = 0; i < ret.length; i++) {
                if(i!= flag){
                    ret[i] = 0;
                }else{
                    int max = 1;
                    for (int i1 = 0; i1 < A.length; i1++) {
                        if(A[i1] != 0){
                            max*=A[i1];
                        }
                    }
                    ret[flag] = max;
                }

            }
            return ret;
        }
        for (int i = 0; i < ret.length; i++) {
            ret[i] = sum/A[i];
        }
        return ret;
    }
}


发表于 2021-10-30 22:08:47 回复(0)

双重循环,外循环从小到大,内循环从大到小。如果两个循环下标相同则跳过即可。

import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        int res[] = new int[A.length];
        for(int i=A.length-1;i>=0;i--){
            int sum=1;
            for(int j=0;j<A.length;++j){
                if(i!=j)sum*=A[j];        
            }
            res[i]=sum;
        }
        return res;
    }
}
发表于 2021-09-24 17:07:30 回复(0)
/*
构建乘积数组
    
结果B[]写为A[]的矩阵
B[i]的为每行A[i]的乘积,中间凑1。
    
B[i]和A[i]的累乘关系递推
时间O(n)
递推:B[i]=B[i-1]*A[i-1]
    
先保存左下角的结果,右上角的结果可以再声明a=1,b=1来递推
然后再乘到结果里
*/
    /*
    构建乘积数组
    
    把结果B[]写为A[]的矩阵,
    B[i]的为每行A[i]的乘积,中间凑1。
    
    用B[i]和A[i]的累乘关系,递推。
    时间O(n)。
    递推:B[i]=B[i-1]*A[i-1]
    
    先保存左下角的结果,右上角的结果可以再声明a=1,b=1来递推
    然后再乘到结果里
    */
    public int[] multiply(int[] A) {
        int n = A.length;
        int[] B = new int[n];
        B[0] = 1;
        //下三角,用A与B的关系递推
        //B[i]=B[i-1]*A[i-1]
        for(int i = 1;i < n;i++){
            B[i] = B[i-1] * A[i-1];
        }
        //上三角,用a和b来递推
        int a = 1,b = 1;
        for(int i = n-1;i > 0;i--){
            b = a * A[i];
            B[i-1] *= b;
            a = b;
        }
        return B;
    }


发表于 2021-09-01 17:51:26 回复(0)
import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        int[] B = new int[A.length];
        B[0] = 1;
        for (int n=1;n<A.length;n++){
            B[0] *= A[n];
        }
        B[A.length-1] = 1;
        for (int n=0;n<A.length-1;n++){
            B[A.length-1] *= A[n];
        }
        for (int n=1;n<A.length-1;n++){
            B[n] = 1;
            for (int i=0;i<A.length;i++){
                if (n == i) continue;
                B[n] *= A[i];
            }
        }
        return B;
    }
}

发表于 2021-08-27 12:40:53 回复(0)