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編程題彙總(持續更新中……)

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