【春节篇】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),是面试中的推荐写法。
相关推荐
知识浅谈5 小时前
DeepSeek V4 和 GPT-5.5 在同一天发布了??我也很懵,但对比完我悟了
算法
DeepModel5 小时前
通俗易懂讲透 Q-Learning:从零学会强化学习核心算法
人工智能·学习·算法·机器学习
田梓燊5 小时前
力扣:19.删除链表的倒数第 N 个结点
算法·leetcode·链表
简简单单做算法7 小时前
基于GA遗传优化双BP神经网络的时间序列预测算法matlab仿真
神经网络·算法·matlab·时间序列预测·双bp神经网络
阿豪学编程7 小时前
面试题map/unordered相关
数据结构
guygg887 小时前
利用遗传算法解决列车优化运行问题的MATLAB实现
开发语言·算法·matlab
武藤一雄7 小时前
19个核心算法(C#版)
数据结构·windows·算法·c#·排序算法·.net·.netcore
sali-tec7 小时前
C# 基于OpenCv的视觉工作流-章52-交点查找
图像处理·人工智能·opencv·算法·计算机视觉
梦想的颜色8 小时前
mongoTemplate + Java 增删改查基础介绍
数据结构·数据库·mysql
yu85939588 小时前
MATLAB连续线性化模型预测控制(SL-MPC)
算法·机器学习·matlab