【春节篇】LeetCode 热题 100 之 238.除了自身以外数组的乘积

祝大家新年快乐!!!身体健康!!!万事顺意!!!

核心思路

题目要求返回数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积,且禁止使用除法,时间复杂度需为 O (n)。

核心解法是前缀积 + 后缀积

  1. 前缀积数组prefix[i] 表示 nums[0] * nums[1] * ... * nums[i-1](即 nums[i] 左侧所有元素的乘积)。
  2. 后缀积数组suffix[i] 表示 nums[i+1] * nums[i+2] * ... * nums[n-1](即 nums[i] 右侧所有元素的乘积)。
  3. 最终结果:answer[i] = prefix[i] * suffix[i]

解法一:使用前缀积和后缀积数组(空间复杂度 O (n))

实现

复制代码
public int[] productExceptSelf(int[] nums) {
    int n = nums.length;
    int[] prefix = new int[n];
    int[] suffix = new int[n];
    int[] answer = new int[n];

    // 计算前缀积:prefix[i] 是 nums[0..i-1] 的乘积
    prefix[0] = 1;
    for (int i = 1; i < n; i++) {
        prefix[i] = prefix[i - 1] * nums[i - 1];
    }

    // 计算后缀积:suffix[i] 是 nums[i+1..n-1] 的乘积
    suffix[n - 1] = 1;
    for (int i = n - 2; i >= 0; i--) {
        suffix[i] = suffix[i + 1] * nums[i + 1];
    }

    // 结果 = 前缀积 * 后缀积
    for (int i = 0; i < n; i++) {
        answer[i] = prefix[i] * suffix[i];
    }
    return answer;
}

复杂度分析

  • 时间复杂度:O (n),三次线性遍历。
  • 空间复杂度:O (n),使用了两个额外数组。

解法二:原地优化(空间复杂度 O (1),进阶要求)

思路

  1. 先用 answer 数组存储前缀积。
  2. 用一个变量 right 从右向左遍历,实时维护当前位置的后缀积,直接乘到 answer 上,从而省去后缀积数组。

实现

复制代码
public int[] productExceptSelf(int[] nums) {
    int n = nums.length;
    int[] answer = new int[n];

    // 第一步:计算前缀积,存入 answer 数组
    answer[0] = 1;
    for (int i = 1; i < n; i++) {
        answer[i] = answer[i - 1] * nums[i - 1];
    }

    // 第二步:从右向左遍历,用变量 right 维护后缀积
    int right = 1;
    for (int i = n - 1; i >= 0; i--) {
        answer[i] = answer[i] * right;
        right = right * nums[i]; // 更新后缀积,包含当前元素
    }

    return answer;
}

示例验证(nums = [1,2,3,4]):

  1. 前缀积阶段:answer = [1, 1, 2, 6]
  2. 从右向左遍历:
    • i=3: answer[3] = 6 * 1 = 6, right = 1 * 4 = 4
    • i=2: answer[2] = 2 * 4 = 8, right = 4 * 3 = 12
    • i=1: answer[1] = 1 * 12 = 12, right = 12 * 2 = 24
    • i=0: answer[0] = 1 * 24 = 24, right = 24 * 1 = 24
  3. 最终结果:[24, 12, 8, 6],与示例一致。

复杂度分析

  • 时间复杂度:O (n),两次线性遍历。
  • 空间复杂度:O (1),仅使用常数额外空间(输出数组不计入)。

总结

  • 基础解法( 左右乘积列表**)**:通过前缀积和后缀积数组,清晰地将问题拆解为 "左侧乘积 × 右侧乘积",易于理解。
  • 进阶解法:通过原地复用数组和变量,将空间复杂度优化到 O (1),是面试中的推荐写法。
相关推荐
xsyaaaan4 小时前
leetcode-hot100-双指针:283移动零-11盛最多水的容器-15三数之和-42接雨水
算法·leetcode
炽烈小老头7 小时前
【每天学习一点算法 2026/03/08】相交链表
学习·算法·链表
一碗白开水一8 小时前
【工具相关】OpenClaw 配置使用飞书:打造智能飞书助手全流程指南(亲测有效,放心享用)
人工智能·深度学习·算法·飞书
仰泳的熊猫8 小时前
题目2194:蓝桥杯2018年第九届真题-递增三元组
数据结构·c++·算法
Tisfy8 小时前
LeetCode 1888.使二进制字符串字符交替的最少反转次数:前缀和O(1)
算法·leetcode·字符串·题解
滴滴答滴答答9 小时前
机考刷题之 9 LeetCode 503 下一个更大元素 II
算法·leetcode·职场和发展
飞Link9 小时前
梯度下降的优化算法中,动量算法和指数加权平均的区别对比
人工智能·深度学习·算法
啊哦呃咦唔鱼9 小时前
LeetCode hot100-15 三数之和
数据结构·算法·leetcode
_日拱一卒9 小时前
LeetCode(力扣):杨辉三角||
算法·leetcode·职场和发展
rqtz9 小时前
基于I2C总线的IMU-磁力计融合算法与数据共享
算法·iic·espidf·qmc5883p·icm42670p·imu磁力计融合