剑指 Offer 66. 构建乘积数组

439 阅读2分钟

剑指 Offer 66. 构建乘积数组

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

1、题目📑

给定一个数组 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]。不能使用除法

实例1

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

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

提示:

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

2、思路🧠

方法一:左侧乘积 ✖ 右侧乘积

可能有小伙伴没有理解题目的意思,这里我简单解释一下,B[i] = 去除A[i] 其余A数组中的数的乘积,也就是说前面的乘积 ✖ 后面的乘积,因此只需要统计出当前这个点左半边的乘积与右半边的乘积。

image-20220427121620648

分析题目主要存在3种情况

  1. 构建左侧乘积
  2. 构建右侧乘积
  3. 对应位置左右乘积进行相乘

构建过程

  1. 构建左侧乘积数组

    int[] left = new int[a.length];
    int temp = 1;
    for (int i = 0; i < a.length; i++) {
    	left[i] = p;
    	p *= a[i];
    }
    
  2. 构建右侧乘积数组

    int[] right = new int[a.length];
    temp = 1;
    for (int i = a.length - 1; i >= 0; i--) {
    	right[i] = p;
        p *= a[i];
    }
    
  3. 对应位置左右乘积进行相乘

    int[] res = new int[a.length];
    for (int i = 0; i < a.length; i++) {
    	res[i] = left[i] * right[i];
    }
    return ans;
    

废话少说~~~~~上代码!

3、代码👨‍💻

第一次commit AC

class Solution {
    public int[] constructArr(int[] a) {
        int b [] = new int [a.length];
        int res = 1;
        for(int i = 0; i < a.length; i++) {
            b[i] = res;
            res *= a[i];
        }
        res = 1;
        for(int i = a.length - 1; i>= 0; i--) {
            b[i] *= res;
            res *= a[i];
        }
        return b;
    }
}

时间复杂度:O(N) 其中 N 为数组长度,两轮遍历数组 a ,使用 O(N) 时间。

空间复杂度:O(1)

image-20220427121700622

4、总结

该题目的难点在于 不能使用除法 ,即需要 只用乘法 生成数组 B 。还有一个问题在于如果输入数组中出现 0,那么 先计算给定数组所有元素的乘积,然后对数组中的每个元素 x,将总的乘积除以 x 来求得除自身值的以外数组的乘积 失效了。而且在问题中说明了不允许使用除法运算。这增加了这个问题的难度。

❤️‍来自专栏《LeetCode基础算法题》欢迎订阅❤️‍

厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。

对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!

原题链接:剑指 Offer 66. 构建乘积数组 - 力扣(LeetCode) (leetcode-cn.com)