构建乘积数组

题目要求:

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

对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。

 

思路:

实际上我们仔细看这张图,B[i]其实就是对角线划分的左区域和右区域的一个乘积,那么我们就可以将这两个区域分别遍历,得到B[i]的部分乘积值。

我们首先来分析左下区域的B[i]的部分乘积,B[0]为1,B[1]其实就是A[0],B[2]就是B[1] *A[1],...,以此类推,即:

B[0] = 1;

B[1] = B[0] * A[0];

...

B[n-1] = B[n-2] * A[n-2] = 1 * A[0] * A[1] *....*A[n-2]; (注意此时B[n-1]已经完成了计算,那么反过来退右边的三角区域时不用再考虑它了)

接着我们同理倒着分析右边的三角区域:

每一行都要用前面推出来的B[i]来乘以右边剩下的乘积,右边的乘积我们可以像刚刚那样计算,但是不能直接使用B[i]来存值了,因为之前的每一个B[i]的值我们还要用,那么此刻我们就需要一个暂存变量,来存储右边的乘积。

即倒着来,temp = 1;

temp = temp * A[n-1]

B[n-2] = B[n-2] * temp;

分析结束了,我们放上代码:

import java.util.ArrayList;
public class Solution {
    // 思路:实际上就是求把对应位置置1后每行的乘积,可以先算下半区,再算上半区
    public int[] multiply(int[] A) {
        int[] B = new int[A.length];
        // 首先计算下三角区
        // 
        B[0] = 1;
        for(int i = 1;i < B.length;i++){
            B[i] = B[i-1] * A[i-1];// 攒下三角的乘积
        }
        int temp = 1;
        for(int i = B.length-2;i >= 0;i--){
            temp *= A[i+1]; // 攒上半区的乘积
            B[i] *= temp;
        }
        return B;
    }
}

 

 

题目来自:牛客网剑指offer。

答案参考:https://www.nowcoder.com/profile/645151/codeBookDetail?submissionId=1516453

(最开始还是惯性地使用暴力,看了别人的之后对时间复杂度进行了一个优化,希望以后也能有比较好的算法思维呀!加油)

ps:这个方法相较暴力,时间复杂度从O(n^2)降低到了O(2n),但是空间复杂度好像是升高了,难解。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值