Python练习题:实现除自身以外元素的乘积

题目

给定一个长度为 n 的整数列表 nums,其中 n > 1,返回输出列表 res ,其中 res[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

例如:

给定一个列表:[1, 2, 3, 4],返回结果:[24, 12, 8, 6]

注意:实现过程中,不允许使用 除法 ,且要求时间复杂度为O(n)

实现思路

遍历列表,对于遍历到的当前元素,如果要计算出除其自身以外整数的乘积,我们只需要分别求出 左侧所有元素的乘积 和 右侧所有元素的乘积 即可。

假设给定列表为:[1, 2, 3, 4],其具体计算过程如下:
在这里插入图片描述

首先,正序遍历,分别求出每个元素左侧的所有元素的乘积,结果保存到 left_product_list
接着,倒序遍历,分别求出每个元素右侧的所有元素的乘积,结果保存到 right_product_list
最后,对每个遍历到的元素,最终乘积结果 = 左乘积 * 右乘积,把结果保存到一个列表,最终返回即可

代码实现

def productExceptSelf(nums):
    res = []
    left_product_list, right_product_list = [1], [1]
    left_product, right_product = 1, 1
    for i in range(1, len(nums)):  # 从第一个元素开始,计算每个元素左侧的所有元素的乘积
        left_product *= nums[i - 1]
        left_product_list.append(left_product)
    for i in range(len(nums) - 2, -1, -1):  # 从倒数第二个元素开始,计算每个元素右侧的所有元素的乘积
        right_product *= nums[i + 1]
        right_product_list.append(right_product)
    for i in range(len(nums)):  # 注意 left_product_list 是正序计算,right_product_list 是倒序计算
        left, right = left_product_list[i], right_product_list[len(nums) - 1 - i]
        res.append(left * right)
    return res

上面的实现方式中,我们专门定义了两个列表:left_product_listright_product_list,分别记录左侧元素乘积、右侧元素乘积,这里的空间复杂度是 O(n),如果我们不考虑返回列表空间的话,那么其实可以针对上方代码进行优化,让其空间复杂度降到 常数级别 O(1):

def productExceptSelf(nums):
    res = [1] * len(nums)
    left_product, right_product = 1, 1
    for i in range(1, len(nums)):  # 从第一个元素开始,计算每个元素左侧的所有元素的乘积
        left_product *= nums[i - 1]
        res[i] *= left_product
    for i in range(len(nums) - 2, -1, -1):  # 从倒数第二个元素开始,计算每个元素右侧的所有元素的乘积
        right_product *= nums[i + 1]
        res[i] *= right_product
    return res

上面的实现方式中,我们不再专门使用额外的列表来保存左右侧元素乘积,而是将最终返回列表设置为一个固定长度的列表,接着直接修改列表中的元素值,如此一来,如果不考虑返回列表空间的前提下,其空间复杂度就降到 O(1)。

从上面的代码中,可以发现我们对列表进行了2次遍历,第一次正序遍历是为了计算左乘积,第二次倒序遍历是为了计算右乘积,在这里其实我们也可以继续优化,仅通过一次遍历来完成,最终优化后代码如下:

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def productExceptSelf(nums):
    """
    针对 [1, 2, 3, 4] ,遍历过程中,每个元素的左右累积均相乘
    i=0, res[0]乘左累积,res[3]乘右累积;
    i=1, res[1]乘左累积,res[2]乘右累积;
    i=2, res[2]乘左累积,res[1]乘右累积;
    i=3, res[3]乘左累积,res[0]乘右累积
    """
    res = [1] * len(nums)
    left_product, right_product = 1, 1
    for i in range(len(nums)):
        res[i] *= left_product
        left_product *= nums[i]  # 下标 i 位置元素的左侧所有元素的累积
        res[len(nums) - 1 - i] *= right_product
        right_product *= nums[len(nums) - 1 - i]  # 下标 len - 1 - i 位置元素的右侧所有元素的累积
    return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值