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

【练习】力扣热题100 除自身以外数组的乘积

题目

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例 1:

输入: nums = [1,2,3,4]
输出: [24,12,8,6]
示例 2:

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

来源:力扣热题100 除自身以外数组的乘积


题解

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> a(n, 1);

        // 计算前缀积
        for (int i = 1; i < n; i++) {
            a[i] = a[i - 1] * nums[i - 1];
        }

        // 计算后缀积并更新结果
        int t = 1;
        for (int i = n - 1; i >= 0; i--) {
            a[i] *= t;
            t *= nums[i];
        }

        return a;
    }
};

计算除自身以外数组的乘积。它的目标是给定一个整数数组 nums,返回一个数组 a,其中 a[i]nums 中除 nums[i] 之外所有元素的乘积。要求时间复杂度为 O(n),并且不能使用除法。

以下是代码的详细分析:


代码逻辑分析:

  1. 初始化结果数组 a

    vector<int> a(n, 1);
    
    • 创建一个大小为 n 的数组 a,并初始化为 1。这个数组将用于存储最终结果。
  2. 计算前缀积

    for (int i = 1; i < n; i++) {
        a[i] = a[i - 1] * nums[i - 1];
    }
    
    • 从左到右遍历数组,计算每个位置左侧所有元素的乘积,并存储在 a 中。
    • 例如,a[i] 表示 nums[0] * nums[1] * ... * nums[i-1]
    • 这一步完成后,a 数组存储了每个位置左侧的乘积。
  3. 计算后缀积并更新结果

    int t = 1;  // 初始化后缀积为 1
    for (int i = n - 1; i >= 0; i--) {
        a[i] *= t;  // 将后缀积乘到 a[i] 上
        t *= nums[i];  // 更新后缀积
    }
    
    • 从右到左遍历数组,使用变量 t 累乘右侧元素,并将结果乘到 a[i] 上。
    • 例如,a[i] 最终等于 a[i] * (nums[i+1] * nums[i+2] * ... * nums[n-1])
    • 这一步完成后,a 数组中的每个元素就是除自身外所有元素的乘积。

举例说明:

假设输入数组为 nums = [1, 2, 3, 4],运行过程如下:

  1. 初始化

    • a = [1, 1, 1, 1]
  2. 计算前缀积

    • i = 1a[1] = a[0] * nums[0] = 1 * 1 = 1
    • i = 2a[2] = a[1] * nums[1] = 1 * 2 = 2
    • i = 3a[3] = a[2] * nums[2] = 2 * 3 = 6
    • 此时 a = [1, 1, 2, 6]
  3. 计算后缀积并更新结果

    • 初始化 t = 1
    • i = 3a[3] *= 1 = 6 * 1 = 6t = 1 * 4 = 4
    • i = 2a[2] *= 4 = 2 * 4 = 8t = 4 * 3 = 12
    • i = 1a[1] *= 12 = 1 * 12 = 12t = 12 * 2 = 24
    • i = 0a[0] *= 24 = 1 * 24 = 24t = 24 * 1 = 24
    • 最终 a = [24, 12, 8, 6]

时间复杂度:

  • O(n),其中 n 是数组的长度。我们只需要遍历数组两次(一次计算前缀积,一次计算后缀积)。

空间复杂度:

  • O(1),除了输出数组 a 外,只使用了常数额外空间(变量 t)。

总结:

这段代码是一个非常高效的实现,通过前缀积和后缀积的方法,完美地解决了“除自身以外数组的乘积”问题。它的时间复杂度为 O(n),空间复杂度为 O(1)(除了输出数组),并且避免了除法操作。如果需要进一步优化,可以添加边界条件处理或改进变量命名。


http://www.kler.cn/a/504113.html

相关文章:

  • 使用葡萄城+vue实现Excel
  • Vue.js前端框架教程16:Element UI的el-dialog组件
  • Python在Excel工作表中创建数据透视表
  • 当当网热销书籍数据采集与可视化分析
  • 为AI聊天工具添加一个知识系统 之32 三“中”全“会”:推理式的ISA(父类)和IOS(母本)以及生成式CMN (双亲委派)之1
  • Linux--CPU系统资源命令查看--详解
  • WinForm如何跨线程更新界面
  • 在vscode中使用R-1
  • “代驾”小程序查漏补缺
  • 【漫话机器学习系列】048.编码有序类别特征(Encoding Ordinal Categorical Features)
  • C#里使用libxl设置EXCEL里公式计算的例子
  • Golang——并发控制
  • macos遇到You have not agreed to the Xcode license agreements.
  • SpringBoot之OriginTrackedPropertiesLoader类源码学习
  • 网管平台(进阶篇):路由器的管理实践
  • 华三S6520交换机配置console和ssh
  • 【数据结构学习笔记】19:跳表(Skip List)
  • 浅谈计算机网络02 | SDN控制平面
  • 一个使用 Golang 编写的新一代网络爬虫框架,支持JS动态内容爬取
  • 【漫话机器学习系列】047.指数型线性单元(Exponential Linear Units,ELU)
  • 1.4 给应用添加service,执行扩容和滚动更新
  • TDSQL 内存占用解析一例
  • Golang|单机并发缓存
  • 24. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--预算扣除、退回、补充
  • 华为2024嵌入式研发面试题
  • Adobe与MIT推出自回归实时视频生成技术CausVid。AI可以边生成视频边实时播放!