Python编程题42--除自身以外元素的乘积

题目

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

例如:

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

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

实现思路

  • 遍历列表,对于遍历到的当前元素,如果要计算出除其自身以外整数的乘积,我们只需要分别求出 左侧所有元素的乘积右侧所有元素的乘积 即可。假设给定列表为:[1, 2, 3, 4],其具体计算过程如下:
第一个数 第二个数 第三个数 第四个数
给定列表的所有元素 1 2 3 4
当前元素左侧部分的乘积 1 1 1 * 2 1 * 2 * 3
当前元素右侧部分的乘积 2 * 3 * 4 3 * 4 4 1
左乘积 * 右乘积 1 * 2 * 3 * 4 1 * 3 * 4 1 * 2 * 4 1 * 2 * 3 * 1
计算最终结果 24 12 8 6
  • 首先,正序遍历,分别求出每个元素左侧的所有元素的乘积,结果保存到 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_list、right_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次遍历,第一次正序遍历是为了计算左乘积,第二次倒序遍历是为了计算右乘积,在这里其实我们也可以继续优化,仅通过一次遍历来完成,最终优化后代码如下:

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

更多Python编程题,等你来挑战:Python编程题汇总(持续更新中……)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章