【刷题日记】剑指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]。不能使用除法。

开始思考这个问题:
因为不许用除法,我就构建了两个数组保存中间结果:

mid_1 = [1, A[0], A[0]A[1], A[0]A[1]A[2], …, A[0]A[1],…A[N-1]]

mid_2 = [A[1]A[2]…A[N-1], A[2]A[3]…A[N-1], A[3]…A[N-1], A[4]A[5]…A[N-1],… 1 ]$

构建完这两个数组以后,

B[i] = mid_1[i] *mid_2[i]

反正这样写挺笨的,但还是可以通过的嘛~

def multiply(A):
    N = len(A)
    if N ==0 or N ==1:
        return []
    B = []
    mid_1 =[]
    mid_2 =[]
    # 每个数组的长度为 N
    for i in range(0,N):
        tmp = 1
        for j in range(i):
            tmp*=A[j]
        mid_1.append(tmp)
        tmp = 1
        for k in range(i+1,N):
            tmp*=A[k]
        mid_2.append(tmp)
    for i in range(N):
        B[i] =mid_1[i]*mid_2[i]
    return B

后来发现呢,这两个中间数组其实可以不要啊,只要把B[i]初始化为1分成两部分算就好了

左边: B[i] *= A[left] , left的范围是 [0, i-1]

接着乘右边: B[i] *= A[right], right 的范围是 [i+1, N-1]

def multiply2(A):
    N = len(A)
    if N==1 or N==0:
        return []
    # 避坑指南:为了防止index越界,在知道数组大小时可以全部初始化
    # 这里对元素做乘法运算,初始化为1
    # 对于要做加法运算的数组可以初始化为0
    B = [1 for i in range(N)]
    for i in range(N):
        for left in range(i):
            B[i]*=A[left]
        for right in range(i+1,N):
            B[i] *=A[right]
    return B

但是这里还是有一个问题,就是在计算B的过程中存在很多重复运算。B[i] 中存在B[i-1]中计算过的很多部分.
在这里插入图片描述
比如从上图一个长度为5的数组的计算图可以看出来每一行都存在重复。
1的左边每次下面一行(第i行)都比上面一行多一个A[i-1]
1的右边每次上面一行 (第i行) 都比下面一行多一个A[i+1]
于是可以这样计算:
左边自上而下:
i 从1到N-1, B[i] = B[i-1]*A[i-1]
右边自下而上:tmp=1
i 从N-2到0,tmp *= A[i+1] , B[i] *=tmp

def multiply(A):
	N = len(A)
	if N == 0 or N ==1:
		return []
	B =[1 for i in range(N)]
	for i in range(1,N):
		B[i] = B[i-1]*A[i-1]
	tmp = 1
	for i in range(N-2,-1,-1):
		tmp *= A[i+1]
		B[i]*=tmp
	return B
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值