Leetcode: 除自身以外数组的乘积

49 阅读3分钟

原题: leetcode.cn/problems/pr…

题目描述

给定一个整数数组 nums,返回一个数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。要求:

  • 不能使用除法
  • 时间复杂度为 O(n)O(n)
  • 空间复杂度为 O(1)O(1)(输出数组不计入空间复杂度)

解题思路

核心思想:通过两次遍历分别计算每个元素左侧和右侧的乘积,最终将两侧乘积相乘得到结果。

  1. 左侧乘积计算
  2. 左侧乘积计算(从左向右遍历):
    • 初始化 `answer:
    • 初始化 answer = 1(首元素左侧无元素)
    • 对于每个位置 ianswer[i] = nums × nums × ... × nums[i-1]
    • 递推公式:answer[i] = answer[i-1] × nums[i-1]
  3. 右侧乘积计算(从右向左遍历):
    • 用变量 right_product 动态维护右侧乘积(初始为1)
    • 对于每个位置 i,将 answer[i] 乘上右侧乘积 right_product
    • 更新 right_product *= nums[i](为下一个元素准备)

关键洞察

  • 将结果分解为左侧乘积 × 右侧乘积
  • 复用输出数组存储中间结果,避免额外空间
  • 右侧乘积通过动态更新变量高效计算

复杂度分析

指标说明
时间复杂度O(n)O(n)两次独立遍历数组
空间复杂度O(1)O(1)仅使用常数变量(输出数组不计入)

代码实现

  • JavaScript
var productExceptSelf = function(nums) {
        const n = function(nums) {
        const n = nums.length;
        const answer = new Array(n).fill(1);

        // 计算左侧乘积
        for (let i = 1; i < n; i++) {
                answer[i] = answer[i-1] * nums[i-1];
        }

        // 计算右侧乘积并合并结果
        let rightProduct = 1;
        for (let i = n-1; i >= 0; i--) {
                answer[i] *= rightProduct;
                rightProduct *= nums[i];
        }

        return answer;
};
  • python
def productExceptSelf(nums):
    n = len(nums)
    answer = [1] * n

    # 计算左侧乘积
    for i in range(1, n):
        answer[i] = answer[i-1] * nums[i-1]

    # 计算右侧乘积并合并结果
    right_product = 1
    for i in range(n-1, -1, -1):
        answer[i] *= right_product
        right_product *= nums[i]

    return answer
  • rust
impl Solution {
    pub fn product_except_self(nums: Vec) -> Vec {
        let n = nums.len();
        let mut answer = vec![1; n];

        // 计算左侧乘积
        for i in 1..n {
            answer[i] = answer[i-1] * nums[i-1];
        }

        // 计算右侧乘积并合并结果
        let mut right_product = 1;
        for i in (0..n).rev() {
            answer[i] *= right_product;
            right_product *= nums[i];
        }

        answer
    }
}

实际应用场景

  1. 信号处理:计算滤波器中每个采样点除自身外的加权乘积
  2. 数据压缩:在矩阵运算中避免零值干扰的权重计算
  3. 金融分析:计算资产组合中各资产对总收益的贡献度(排除自身影响)
  4. 图像处理:像素邻域计算中排除中心像素的影响

相似题目

  1. 乘积最大子数组
    • 解题思路:动态规划维护当前最大/最小乘积
    • 关键差异:关注连续子数组而非全局计算
  2. 数组中的逆序对
    • 解题思路:归并排序过程中统计逆序对
    • 关键差异:涉及顺序关系而非乘积计算
  3. 接雨水
    • 解题思路:双指针计算左右最大边界
    • 关联点:同样需要左右两侧信息计算