返回

剑指 Offer 66:构建乘积数组的两种解法,解析题意,从左往右与从右往左的分析与实现

后端

题意解析

给定一个长度为 n 的数组 nums,要求构建一个长度也为 n 的数组 answer,其中 answer[i] 是除下 nums[i] 之外所有元素的乘积。

从左往右解法

思路:

  • 定义一个前缀积数组 prefix,其中 prefix[i] 是从 nums[0] 到 nums[i] 的乘积。
  • 定义一个后缀积数组 suffix,其中 suffix[i] 是从 nums[i] 到 nums[n-1] 的乘积。
  • 对于每个元素 nums[i],answer[i] 可以表示为 prefix[i-1] * suffix[i+1]。

复杂度分析:

时间复杂度:O(n)。
空间复杂度:O(n)。

实现:

def construct_product_array_left_to_right(nums):
    n = len(nums)
    prefix = [1] * n
    suffix = [1] * n

    # 计算前缀积
    for i in range(1, n):
        prefix[i] = prefix[i-1] * nums[i-1]

    # 计算后缀积
    for i in range(n-2, -1, -1):
        suffix[i] = suffix[i+1] * nums[i+1]

    # 计算答案
    answer = [1] * n
    for i in range(n):
        answer[i] = prefix[i-1] * suffix[i+1]

    return answer

从右往左解法

思路:

与从左往右的解法类似,但我们从右往左计算前缀积和后缀积。

复杂度分析:

时间复杂度:O(n)。
空间复杂度:O(n)。

实现:

def construct_product_array_right_to_left(nums):
    n = len(nums)
    prefix = [1] * n
    suffix = [1] * n

    # 计算后缀积
    for i in range(n-2, -1, -1):
        suffix[i] = suffix[i+1] * nums[i+1]

    # 计算前缀积
    for i in range(1, n):
        prefix[i] = prefix[i-1] * nums[i-1]

    # 计算答案
    answer = [1] * n
    for i in range(n):
        answer[i] = prefix[i-1] * suffix[i+1]

    return answer

总结

两种解法在时间复杂度和空间复杂度上都是相同的。从左往右的解法更容易理解,但从右往左的解法在某些情况下可能更有效率。