图解LeetCode——剑指 Offer 66. 构建乘积数组

简介: 图解LeetCode算法

一、题目

给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即:B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]不能使用除法

二、示例

2.1> 示例:

输入】 [1,2,3,4,5]

输出】 [120,60,40,30,24]

提示:

  • 所有元素乘积之和不会溢出 32 位整数
  • a.length <= 100000

三、解题思路

根据这道题的描述,我们其实很容易就想到,现遍历数组中所有的元素,然后针对每个元素执行乘法操作,得到最终的结果之后,如果需要获得B[i]的值,只需要将总的结果除以A[i]即可。但是,本道题已经指明了不能使用除法,那么上面我们最容易想出来的解决方案就不能使用了。

那么还有什么解决办法吗?我们以A[1,2,3,4,5]为例,如果要组成B数组,需要如下方式计算(其中“”表示略过不计算):

B[0] =  *  2 * 3 * 4 * 5

B[1] = 1 * * 3 * 4 * 5

B[2] = 1 * 2 * * 4 * 5

B[3] = 1 * 2 * 3 * * 5

B[4] = 1 * 2 * 3 * 4 *

那么根据上面从B[0]~B[4]的计算公式可以看出来,整个“计算矩阵”是被分割为两个三角,我们姑且将其称之为“左下角三角”和“右上角三角”。那么针对每个B[i],我们可以得出如下计算公式,即:B[i] = 左下三角区域[i] ✖️ 右上三角区域[i] 。那么我们执行如下方式执行遍历计算:

正序遍历】从B[0]开始到B[n-1],计算的结果是“左下三角形”的值;

逆序遍历】从B[n-1]开始到B[0],在计算“右上三角形”值的同时,再乘以左下三角区域[i]的值,那么就是B[i]最终的结果了。

以上就是这道题的解题思路了,下面我们还是举一个例子,这样更方便和深入的让大家理解这道题的解题过程,我们以A数组为{1,2,3,4,5}为例,来看一下计算B数组的过程。请见下图所示:

image.png

四、代码实现

class Solution {
    public int[] constructArr(int[] a) {
        int len = a.length;
        if (len == 0) return a;
        int[] result = new int[len];
        result[0] = 1;
        // 计算左下三角的乘积
        for (int i = 1; i < len; i++) 
            result[i] = result[i-1] * a[i-1];
        // 计算右上三角的乘积
        for (int i = len - 2, temp = 1 ; i >= 0; i--) {
            temp *= a[i+1];
            result[i] *= temp;
        }      
        return result;
    }
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」


相关文章
|
10月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
400 1
|
算法 C++
Leetcode第53题(最大子数组和)
这篇文章介绍了LeetCode第53题“最大子数组和”的动态规划解法,提供了详细的状态转移方程和C++代码实现,并讨论了其他算法如贪心、分治、改进动态规划和分块累计法。
312 0
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
241 0
Leetcode第三十三题(搜索旋转排序数组)
|
C++
【LeetCode 12】349.两个数组的交集
【LeetCode 12】349.两个数组的交集
125 0
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
436 1
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
382 3
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
394 6
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
Python
【Leetcode刷题Python】1467. 两个盒子中球的颜色数相同的概率
本文介绍了LeetCode第50题"Pow(x, n)"的解法,题目要求实现计算x的n次幂的函数,文章提供了递归分治法的详细解析和Python实现代码。
278 0
|
Python
【Leetcode刷题Python】50. Pow(x, n)
本文介绍了LeetCode第50题"Pow(x, n)"的解法,题目要求实现计算x的n次幂的函数,文章提供了递归分治法的详细解析和Python实现代码。
384 1
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
470 2

热门文章

最新文章

下一篇
开通oss服务