当前位置: 首页 > java >正文

剑指offer67_构建乘积数组

构建乘积数组


给定一个数组A[0, 1, …, n-1],请构建一个数组B[0, 1, …, n-1],其中B中的元素B[i]=A[0]×A[1]×… ×A[i-1]×A[i+1]×…×A[n-1]

不能使用除法。

数据范围

输入数组长度 [0,20]。

样例
输入:[1, 2, 3, 4, 5]输出:[120, 60, 40, 30, 24]

思考题

  • 能不能只使用常数空间?(除了输出的数组之外)

算法思路

核心思想
B[i] 拆解为 左乘积(left[i]) × 右乘积(right[i]

  1. 左乘积A[0] × A[1] × ... × A[i-1](即 i 左侧所有元素的乘积)。
  2. 右乘积A[i+1] × A[i+2] × ... × A[n-1](即 i 右侧所有元素的乘积)。

通过两次遍历分别计算左乘积和右乘积,最终合并结果。

  • 时间复杂度O(n)
    仅需两次线性遍历数组,无嵌套循环。
  • 空间复杂度O(1)(不考虑输出数组 B
    仅使用常数个临时变量(p)。若考虑输出数组,则为 O(n)
class Solution {
public:vector<int> multiply(const vector<int>& A) {int n = A.size();vector<int> B(n);  // 初始化结果数组if (A.empty()) return B;  // 边界条件:空数组直接返回// 第一遍遍历:计算左乘积(B[i] = A[0] × A[1] × ... × A[i-1])for (int i = 0, p = 1; i < n; i++) {B[i] = p;  // 存储左乘积p *= A[i]; // 更新左乘积(累乘A[i])}// 第二遍遍历:计算右乘积并合并结果(B[i] *= A[i+1] × A[i+2] × ... × A[n-1])for (int i = n - 1, p = 1; i >= 0; i--) {B[i] *= p;  // 左乘积 × 右乘积p *= A[i];   // 更新右乘积(反向累乘A[i])}return B;}
};

实例演示(以 A = [1, 2, 3, 4] 为例)

步骤分解:
  1. 初始化
    B = [1, 1, 1, 1](初始值)
  2. 第一次遍历(计算左乘积)
    • i=0: B[0]=1, p=1×1=1
    • i=1: B[1]=1, p=1×2=2
    • i=2: B[2]=2, p=2×3=6
    • i=3: B[3]=6, p=6×4=24
      此时 B = [1, 1, 2, 6](左乘积结果)
  3. 第二次遍历(计算右乘积并合并)
    • i=3: B[3]=6×1=6, p=1×4=4
    • i=2: B[2]=2×4=8, p=4×3=12
    • i=1: B[1]=1×12=12, p=12×2=24
    • i=0: B[0]=1×24=24, p=24×1=24
      最终 B = [24, 12, 8, 6]
验证:
  • B[0] = 2 × 3 × 4 = 24
  • B[1] = 1 × 3 × 4 = 12
  • B[2] = 1 × 2 × 4 = 8
  • B[3] = 1 × 2 × 3 = 6
    结果正确 ✅

关键点

  1. 避免除法:通过分解为左、右乘积的乘法操作。
  2. 空间优化:复用输出数组 B 存储中间结果,减少额外空间。
  3. 两次遍历:第一次正向遍历计算左乘积,第二次反向遍历计算右乘积并合并。
http://www.xdnf.cn/news/15837.html

相关文章:

  • 周志华《机器学习导论》第11章 特征选择与稀疏学习
  • PyTorch里的张量及张量的操作
  • [前端技术基础]CSS选择器冲突解决方法-由DeepSeek产生
  • 前端的测试
  • 如何实战优化SEO关键词提升百度排名?
  • 深度学习图像分类数据集—百种病虫害分类
  • 【KDD2025】时间序列|Merlin:不固定缺失率下时间序列预测新SOTA!
  • C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(一)
  • 服务器上的文件复制到本地 Windows 系统
  • python网络爬虫小项目(爬取评论)超级简单
  • git fork的项目远端标准协作流程 仓库设置[设置成upstream]
  • 快速上手git
  • LINUX入门(二)QT的安装及运行环境搭建
  • 【实习总结】Qt中如何使用QSettings操作.ini配置文件
  • Vue中组件的生命周期
  • 08_Opencv_基本图形绘制
  • Docker实战:使用Docker部署envlinks极简个人导航页
  • 激光雷达和相机在线标定
  • [C/C++安全编程]_[中级]_[如何安全使用循环语句]
  • 语言学校为何成为IT润日路径的制度跳板?签证与迁移结构的工程化拆解
  • 交通出行大前端与 AI 融合:智能导航与出行预测
  • 智能制造——48页毕马威:汽车营销与研发数字化研究【附全文阅读】
  • jxORM--编程指南
  • linux + 宝塔面板 部署 django网站 启动方式:uwsgi 和gunicorn如何选择 ?
  • windows命令提示符cmd使用
  • Django接口自动化平台实现(四)
  • 第 30 场 蓝桥·算法入门赛 题解
  • 制作mac 系统U盘
  • 零基础学习性能测试第一章-为什么会有性能问题
  • 全面解析 JDK 提供的 JVM 诊断与故障处理工具