【春节篇】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),是面试中的推荐写法。
相关推荐
机 _ 长几秒前
05 智算运维|8 张卡怎么才算「捆成一张」:NCCL 实测与拓扑
运维·人工智能·算法·智算运维
早起CaiCai1 小时前
【2023-01 OM】利用深度学习算法融合异质观测实现海洋场降尺度
人工智能·深度学习·算法
梦里寻码1 小时前
我用 NestJS + Vue3 写了一套完整的研发管理系统(58 表 / 229 API / 130 项断言,全开源
前端·后端·算法
猿人谷2 小时前
Surrogate Model:让进化算法学会“预测”,为什么它正在成为智能优化的重要技术?
后端·算法·架构
文丑颜不良啊3 小时前
LeetCode2241~2260题目解析
java·leetcode
文丑颜不良啊3 小时前
LeetCode2321~2340题目解析
java·leetcode
青少儿编程课堂3 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
白杨尚青4 小时前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树
在猴站学算法4 小时前
(《统计学习方法》(第2版) 李航)第2章 感知机算法
学习·算法·机器学习·统计学习