LeetCode 题解:除自身以外数组的乘积

LeetCode 题解:除自身以外数组的乘积

在刷 LeetCode 的过程中,“除自身以外数组的乘积” 是一道经典的数组类题目,这道题不仅考察对数组遍历的理解,还要求在时间和空间复杂度上做到最优。今天就来分享这道题的高效解法,核心思路是通过两次遍历、利用两个变量分别记录左右侧乘积,实现时间复杂度 O (n)、空间复杂度 O (1)的最优解。

题目描述

给你一个长度为 n 的整数数组 nums,返回一个数组 ans,其中 ans [i] 等于 nums 中除 nums [i] 之外其余所有元素的乘积。要求不能使用除法,且在 O (n) 时间复杂度内完成,额外空间复杂度尽可能优化(除了答案数组外,仅使用常数级空间)。

解题思路

核心思想是拆分乘积计算:将 “除当前元素外所有元素的乘积” 拆分为 “当前元素左侧所有元素的乘积 × 当前元素右侧所有元素的乘积”,通过两次遍历分别计算左右侧乘积,最终合并结果。

具体步骤:

  1. 定义两个变量 leftright,分别表示当前元素左侧所有元素的乘积、右侧所有元素的乘积,初始值均为 1(因为单个元素的左侧 / 右侧无元素,乘积为 1)。
  2. 定义答案数组 ans,长度与输入数组 nums 一致。
  3. 左到右遍历:遍历每个元素时,先将当前 left(即该元素左侧所有元素的乘积)存入 ans[i],再更新 leftleft × nums[i](为下一个元素的左侧乘积做准备)。
  4. 右到左遍历:遍历每个元素时,将 ans[i](左侧乘积)乘以当前 right(右侧乘积),得到最终的 “除自身外所有元素的乘积”,再更新 rightright × nums[i](为前一个元素的右侧乘积做准备)。
  5. 遍历完成后,ans 数组即为最终结果。

复杂度分析

  • 时间复杂度:O (n),仅需两次遍历数组,n 为数组长度。
  • 空间复杂度:O (1),除了存储结果的 ans 数组外,仅使用了 leftright 两个常数级变量(题目通常允许忽略答案数组的空间消耗)。

Java 代码

class Solution { public int[] productExceptSelf(int[] nums) { int n = nums.length; // 定义答案数组 int[] ans = new int[n]; // 第一步:左到右遍历,计算每个元素左侧所有元素的乘积 int left = 1; for (int i = 0; i < n; i++) { // 先将左侧乘积存入ans[i] ans[i] = left; // 更新left,为下一个元素的左侧乘积做准备 left *= nums[i]; } // 第二步:右到左遍历,计算右侧乘积并与左侧乘积相乘 int right = 1; for (int i = n - 1; i >= 0; i--) { // 左侧乘积 × 右侧乘积 = 最终结果 ans[i] *= right; // 更新right,为前一个元素的右侧乘积做准备 right *= nums[i]; } return ans; } } 

代码解析

  1. 初始化阶段
    • int n = nums.length; 获取数组长度,用于定义答案数组和遍历边界。
    • int[] ans = new int[n]; 初始化答案数组,存储最终结果。
  2. 左到右遍历
    • left 初始为 1,因为第一个元素左侧无元素,乘积为 1。
    • 遍历到第 i 个元素时,先把 left(左侧乘积)赋值给 ans[i],再让 left 乘以当前元素 nums[i],这样遍历结束后,ans[i] 存储的是第 i 个元素左侧所有元素的乘积。
  3. 右到左遍历
    • right 初始为 1,因为最后一个元素右侧无元素,乘积为 1。
    • 遍历到第 i 个元素时,将 ans[i](左侧乘积)乘以 right(右侧乘积),得到该位置的最终结果;再让 right 乘以当前元素 nums[i],为前一个元素的右侧乘积做准备。

示例验证

以输入 nums = [1,2,3,4] 为例:

  • 左到右遍历后,ans = [1, 1, 2, 6](分别对应每个元素左侧乘积:1、1、1×2、1×2×3)。
  • 右到左遍历:
    • i=3:ans[3] = 6 × 1 = 6right = 1×4=4
    • i=2:ans[2] = 2 × 4 = 8right = 4×3=12
    • i=1:ans[1] = 1 × 12 = 12right = 12×2=24
    • i=0:ans[0] = 1 × 24 = 24right = 24×1=24
  • 最终 ans = [24,12,8,6],符合 “除自身外所有元素乘积” 的结果。

总结

这道题的核心是拆分乘积计算,通过两次遍历分别处理左右侧乘积,避免了使用除法和额外的数组存储左右乘积,是空间优化的经典思路。关键点总结:

  1. 利用两个变量 leftright 分别记录当前元素的左右侧乘积,替代额外数组,实现空间复杂度 O (1);
  2. 两次遍历的顺序(先左后右)保证了每个位置的乘积能被逐步计算;
  3. 遍历过程中 “先赋值后更新” 的逻辑,确保了当前元素不会被包含到自身的左右乘积中。

这种思路不仅适用于这道题,也可以迁移到其他需要 “左右侧遍历” 的数组类题目中,希望能帮助大家理解和掌握~

Read more

Llama-Factory如何设置warmup步数?线性增长策略推荐

Llama-Factory如何设置warmup步数?线性增长策略推荐 在大模型微调实践中,你是否遇到过训练刚开始 loss 就飙升到 NaN 的情况?或者前几个 epoch 损失剧烈震荡,导致最终性能不稳定?这类问题往往不是数据或模型结构的问题,而是学习率调度中一个关键细节被忽略了——warmup 步数的合理设置。 尤其在使用像 Llama-Factory 这样支持全参数微调、LoRA 和 QLoRA 的通用框架时,虽然上手门槛低,但如果对底层优化机制缺乏理解,很容易因为默认配置“跑不动”而误判工具本身的能力。其中,warmup 阶段的设计直接决定了模型能否平稳度过最脆弱的初始训练期。 为什么 warmup 如此重要? 现代大语言模型(LLM)通常拥有数十亿甚至上百亿参数,初始化权重是随机的。训练初期,梯度可能非常大且方向不稳定。如果此时直接使用较高的学习率进行更新,会导致参数跳跃幅度过大,破坏初始学习动态,甚至引发梯度爆炸。 Warmup 机制就是为了解决这个问题:它让学习率从接近零开始,在前若干步中逐步上升至预设的基础学习率。这个“预热”

By Ne0inhk
Chat took too long to get ready.Please ensure...<VSCode\Copilot>

Chat took too long to get ready.Please ensure...<VSCode\Copilot>

在VScode里面,应用Copilot提问,无法解决问题,该怎么解决呢? 1、在vscode里面,按键  ctrl + shift + p,输入setting,即看到setting.json文件 2、在setting.json文件中添加下面两行   "github.copilot.nextEditSuggestions.enabled": true,   "chat.extensionUnification.enabled":false, 参考图片25、26行 3、保存,重启vscode 4、重启后,点击vscode左下角人头像,查看是否有让授权Copilot的,如果有点击一下授权,解决!!! 如果这样无法解决,建议检查账号是不是不能使用Copilot功能了

By Ne0inhk
使用GpuGeek高效完成LLaMA大模型微调:实践与心得分享

使用GpuGeek高效完成LLaMA大模型微调:实践与心得分享

使用GpuGeek高效完成LLaMA大模型微调:实践与心得分享 🌟嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 随着大模型的发展,越来越多的AI开发者开始尝试对开源模型进行微调,以适配垂直场景需求。但由于训练资源昂贵、部署过程繁琐,很多人仍止步于“想做”阶段。 本文将结合我在 GpuGeek 平台 上对 LLaMA 模型的微调实践,分享完整流程、调优经验以及平台带来的优势,帮助更多开发者低门槛开启大模型实践之路。 注册链接:https://gpugeek.com/login?invitedUserId=753279959&source=invited 一、选型与准备 选择模型:LLaMA-7B Meta发布的LLaMA系列模型在性能与资源消耗之间取得了不错的平衡,适合作为个人或中小团队的定制基础模型。我选择了 LLaMA-7B,结合LoRA方法进行微调。 选择平台:GpuGeek 为什么选GpuGeek? ✅ 显卡资源充足、节点丰富:支持多种高性能GPU,

By Ne0inhk

开源还是商用?大模型选型终极指南与实战搭配

一、开源大模型 vs 商用大模型:该怎么选? 1. 概念和许可证上的差异 开源 / 开放权重大模型 模型权重(weights)公开,可下载、本地部署、二次训练。 多数采用 Apache 2.0、MIT 等宽松开源许可(如 Mistral 7B、Mixtral、Gemma、Falcon 等都是 Apache 2.0 或相近许可)。 也有“开放但非真正开源”的,如 Llama 3 / Llama 2:权重可下载,但许可证不是 OSI 认可的开源协议,商业使用有附加条款,需要阅读 Meta 的 Llama License。

By Ne0inhk