【春节篇】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),是面试中的推荐写法。
相关推荐
zyl76521 小时前
FlashAttention 详解:从 GPU 硬件、普通 Attention 到分块计算与 Online Softmax
算法
爱读书的小胖1 天前
LeetCode 122:买卖股票的最佳时机 II(C)解题分析
算法
结局无敌1 天前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
OPEN-F1 天前
ROS2系列教程:上位机建图与导航(原理综合)
算法·机器人
weixin_307779131 天前
C++代码实现MATLAB中的fitrtree函数功能
开发语言·c++·算法·matlab
tomwang03221 天前
路径优化建模、优化算法分类及工程化小结
算法·数学建模·分类
小羊没烦恼!1 天前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
by209991 天前
哈希表——快速找到数据:冲突、删除与扩容的实现
数据结构·c++·哈希算法·散列表
2501_926978331 天前
人机通信协议--人和机器之间的交互想象
人工智能·经验分享·算法·ai写作
行者全栈架构师1 天前
【鸿蒙心迹】互动卡片全链路——把核心功能放到桌面(FormKit 实战)(HarmonyOS 7.x)
前端·算法·架构