zoukankan      html  css  js  c++  java
  • 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编程题汇总(持续更新中……)

    作者:wintest
    本文版权归作者和博客园共有,欢迎转载,但必须在文章页面明显位置给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:

    k
    通过类名调用类方法
    类Area的getArea方法是一个重载方法
    构造cry
    两个lader对象共享bottom
    向一个方法的基本数据类型参数传值
    Circle
    常量的用法
    显示本机时间
  • 原文地址:https://www.cnblogs.com/wintest/p/15781033.html
Copyright © 2011-2022 走看看