LeetCode算法刷题——238. 除自身以外数组的乘积

一、题目描述

二、解题思路

我们可以使用前缀积和后缀积的方法来解决这个问题,避免使用除法:

  1. 对于每个位置 i,我们需要计算 nums[i] 左侧 所有元素的乘积和右侧所有元素的乘积

  2. 先从左到右遍历,计算每个位置左侧所有元素的乘积,存入 answer 数组

  3. 再从右到左遍历,计算每个位置右侧所有元素的乘积,并与左侧乘积相乘得到最终结果

  4. 这样只需要两次遍历,时间复杂度 O(n),空间复杂度 O(1)(不考虑输出数组)

三、完整代码

class Solution {

public:

vector<int> productExceptSelf(vector<int>& nums) {

// 初始化结果数组,大小为 nums.size(),所有元素初始化为1

vector<int> answer(nums.size(), 1);

int sum = 1; // 用于记录右侧乘积

// 第一遍遍历:计算每个位置左侧所有元素的乘积

for (int i = 1; i < nums.size(); i++) {

answer[i] = answer[i - 1] * nums[i - 1];

}

// 第二遍遍历:计算每个位置右侧所有元素的乘积,并与左侧乘积相乘

for (int i = nums.size() - 2; i >= 0; i--) {

sum = sum * nums[i + 1];

answer[i] = sum * answer[i];

}

return answer;

}

};

四、代码解析

1. 初始化结果数组

vector<int> answer(nums.size(), 1);

  • 创建大小为 nums.size() 的向量

  • 所有元素初始化为 1,因为乘法中 1 是单位元

2. 计算左侧乘积

for (int i = 1; i < nums.size(); i++) {

answer[i] = answer[i - 1] * nums[i - 1];

}

  • 从索引 1 开始遍历**(索引 0 的左侧乘积初始化时已经设置为 1)**

  • answer[i] 存储 nums[i] 左侧所有元素的乘积

  • 递推关系:第 i 个位置的左侧乘积 = 第 i-1 个位置的左侧乘积 × nums[i-1]

3. 计算右侧乘积并更新结果

for (int i = nums.size() - 2; i >= 0; i--) {

sum = sum * nums[i + 1];

answer[i] = sum * answer[i];

}

  • 从倒数第二个元素开始向前遍历**(最后一个索引 的右侧乘积初始化时已经设置为 1)**

  • sum 变量累乘右侧元素,初始为 1

  • 对于位置 i,sum 存储 nums[i] 右侧所有元素的乘积

  • 将左侧乘积和右侧乘积相乘得到最终结果

五、语法要点

1. vector初始化大小和数值

vector<int> v(5, 1); // 创建包含5个元素的向量,所有元素初始化为1

2. vector下标赋值的限制

vector<int> v; // 创建空向量

v[0] = 1; // 错误 ❌

v.push_back(1) // 正确 ✅

  • 未初始化的向量不能直接通过下标赋值,只能使用push_back或push_front方法在前后插入!

六、执行示例

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

第一遍遍历(计算左侧乘积):

  • i=0: answer[0] = 1(初始化值)

  • i=1: answer[1] = answer[0] × nums[0] = 1 × 1 = 1

  • i=2: answer[2] = answer[1] × nums[1] = 1 × 2 = 2

  • i=3: answer[3] = answer[2] × nums[2] = 2 × 3 = 6

  • 此时 answer = [1, 1, 2, 6]

第二遍遍历(计算右侧乘积并更新):

  • 初始化 sum = 1

  • i=2: sum = 1 × nums[3] = 1 × 4 = 4, answer[2] = 4 × 2 = 8

  • i=1: sum = 4 × nums[2] = 4 × 3 = 12, answer[1] = 12 × 1 = 12

  • i=0: sum = 12 × nums[1] = 12 × 2 = 24, answer[0] = 24 × 1 = 24

  • 最终 answer = [24, 12, 8, 6]

七、总结

本文介绍了计算除自身以外数组乘积的高效算法。通过分别计算每个元素的左侧乘积和右侧乘积,然后将两者相乘,我们可以在 O(n) 时间复杂度内解决问题,且不需要使用除法。算法的关键在于两次遍历:第一次计算左侧乘积,第二次计算右侧乘积并更新结果。这种方法空间复杂度为 O(1)(不考虑输出数组),是解决此类问题的最优解法。同时,我们学习了 vector 的正确初始化方法,避免直接通过下标访问未初始化的向量元素。

相关推荐
hhcccchh9 分钟前
学习vue第十三天 Vue3组件深入指南:组件的艺术与科学
javascript·vue.js·学习
sprintzer12 分钟前
1.6-1.15力扣数学刷题
算法·leetcode·职场和发展
jiang_bluetooth14 分钟前
channel sounding基于探测序列的时延和相位差算法
算法·蓝牙测距·channel sound·gfsk·蓝牙6.0
玖釉-14 分钟前
[Vulkan 学习之路] 16 - 最终章:渲染循环与同步 (Rendering & Presentation)
c++·windows·图形渲染
踩坑记录21 分钟前
leetcode hot100 53.最大子数组和 动态规划 medium
leetcode·动态规划
狗狗学不会23 分钟前
Pybind11 封装 RK3588 全流程服务:Python 写逻辑,C++ 跑并发,性能起飞!
c++·人工智能·python·目标检测
DYS_房东的猫29 分钟前
《 C++ 零基础入门教程》第10章:C++20 核心特性 —— 编写更现代、更优雅的 C++
java·c++·c++20
地平线开发者30 分钟前
征程 6 算法工具链 | PTQ 深度使用指南
算法·自动驾驶
心枢AI研习社32 分钟前
python学习笔记8--破茧与连接:Python HTTP 全球协作实战复盘
笔记·python·学习
小黄人软件33 分钟前
蓝色清爽discuz门户论坛模板 ENET新锐版 安装
学习