剑指offer - 构建乘积数组

4.构建乘积数组

题目描述
给定一个数组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];)

img

思路一:暴力法,本能想到的方法

public class Title51 {
    public static int[] multiply(int[] A) {
        if (A == null || A.length <= 1) {
            return null;
        }
    int len = A.length;
    int[] B = new int[len];
     for (int i = 0; i < len; i++) {
        int res = 1;
        for (int j = 0; j < len; j++) {
            if (j != i) {//找到不是A[i]的值
                res *= A[j];
            }
        }
        B[i] = res;
        }
    return  B;
    }

思路二:设置两个数组分别装B[i]左右两个三角需要相乘的部分
这道题的中心思想是将返回的数据列成一个矩阵,每一个矩阵的行向量都是一个从a(0)到a(n-1) ,然后这个对角线都是1.那么此时B0的值就是A0为一,剩下的行向量相乘。
解释下代码,设有数组大小为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]均已经得到正确计算。
/

package main.java.com;
import java.util.ArrayList;
 /

public class Title51 {
    public static int[] multiply(int[] A) {
      if (A == null || A.length <= 1) {
            return A;
        }
        int len = A.length;
        int[] B = new int[len];
        int[] Left = new int[len];
        int[] Right = new int[len];
        //计算左三角
        Left[0] = 1;

        for (int i = 1; i < len; i++) {
            Left[i] = Left[i-1] * A[i-1];
        }
        //计算右三角
        Right[len-1] = 1;
        for (int j = len-2; j >= 0; j--) {
            Right[j] = Right[j+1] * A[j+1];
        }
        //其中B中的元素B[i]=左三角*右三角=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]
        for (int i = 0; i < len; i++) {
            B[i] = Right[i] * Left[i];
        }
        return B;
    }

思路三

比思路二少一个for循环,这道题的中心思想是将返回的数据列成一个矩阵,每一个矩阵的行向量都是一个从a(0)到a(n-1),然后这个对角线都是1.那么此时B0的值就是A0为一,剩下的行向量相乘。

public class Title51 {
    public static int[] multiply(int[] A) {
        int length = A.length;
        int[] B = new int[length];
        B[0] = 1;
        //解决左三角
        for (int i = 1; i < length; i++) {//这里完成了B[1]~B[n-1]的左三角对应相乘的部分,B[0]左三角对应相乘的部分=1不用管
            B[i] = B[i - 1] * A[i - 1];
        }
        //解决右三角
        int temp = 1;
        for (int j = length - 2; j >= 0; j--) {//这里完成了B[0]~B[n-1]的右三角对应相乘的部分,B[n-1]右三角要乘的=1不用管
            temp *= A[j + 1];//temp始终会记录值,每次只需要加上这行上三角没有乘进来的数就可了。
            B[j] *= temp;//把B[i]左三角部分与右三角部分相乘,其中B[n-1]在上一个for循环中已经解决,所以这里取不到也无所谓
        }
        return B;
    }

测试代码

  
        public static void main (String[]args){
            int[] A = {1, 2, 3, 4};
            int[] B = multiply(A);
            for (Integer i : B) {
                System.out.println(i);
            }
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值