Bootstrap

【剑指Offer】个人学习笔记_66_构建乘积数组

刷题日期:下午4:42 2021年5月28日星期五

个人刷题记录,代码收集,来源皆为leetcode

经过多方讨论和请教,现在打算往Java方向发力

主要答题语言为Java

题目:

剑指 Offer 66. 构建乘积数组

难度中等117

给定一个数组 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,2,3,4,5]
输出: [120,60,40,30,24]

提示:

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

既然a的长度能到十万,肯定不能双层遍历,要不然指定超时。

肯定得想办法把目前的结果存下来,在计算下一个的时候,直接经过运算得出结果,一层遍历完成解答。

初始解答:

class Solution {
    public int[] constructArr(int[] a) {
        if (a.length <= 1) return a;
        int product = 1;
        for(int i = 0; i < a.length; i++) {
            if(a[i] == 0) boolean falg = true;
            product *= a[i];
        }
        int[] res = new int[a.length];
        for(int i = 0; i < a.length; i++) {
            res[i] = product / a[i];
        }
        return res;
    }
}

没想到里面还有0,最后执行的输入:[1, 2, 0, 4, 5]

如果有0的话,除了0以外的都是0,如果两个0的话那么都是0。

题目还要求不能用除法,那么打扰了。

学习K神

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

执行结果:通过

显示详情 添加备注

执行用时:2 ms, 在所有 Java 提交中击败了82.65%的用户

内存消耗:51.4 MB, 在所有 Java 提交中击败了5.18%的用户

学习他人:

方法一:

Leslie zjz 2020-02-28

执行用时 : 1 ms , 在所有 Java 提交中击败了 100.00% 的用户 内存消耗 : 54.8 MB , 在所有 Java 提交中击败了 100.00% 的用户

class Solution {
    public int[] constructArr(int[] a) {
	int n = a.length;
    int[] B = new int[n];
    for (int i = 0, product = 1; i < n; product *= a[i], i++)       /* 从左往右累乘 */
        B[i] = product;
    for (int i = n - 1, product = 1; i >= 0; product *= a[i], i--)  /* 从右往左累乘 */
        B[i] *= product;
    return B;
    }
}

方法二:

洪L1 (编辑过)2020-04-18

class Solution {
    public int[] constructArr(int[] a) {
        int[] res = new int[a.length];
        for (int i = 0, cur = 1; i < a.length; i++) {
            res[i] = cur;   // 先乘左边的数(不包括自己)
            cur *= a[i];
        }
        for (int i = a.length - 1, cur = 1; i >= 0; i--) {
            res[i] *= cur;  // 再乘右边的数(不包括自己)
            cur *= a[i];
        }
        return res;
    }
}

方法三:

小菜鸟L1 2021-03-20

class Solution {
    public int[] constructArr(int[] a) {
        int n=a.length; 
        int[]b=new int[n];
        if(n==0) return b;
        //用两个dp数组来存储i左侧的乘积和右边的乘积。
        int[]l=new int[n];
        int[]r=new int[n];
        l[0]=1;r[n-1]=1;
        for(int i=1;i<n;i++){
            l[i]=l[i-1]*a[i-1];
        }
        for(int i=n-2;i>=0;i--){
            r[i]=r[i+1]*a[i+1];
        }
        for(int i=0;i<n;i++)
           b[i]=l[i]*r[i];
        return b;
    }
}

方法四:

K神 解题思路:
本题的难点在于 不能使用除法 ,即需要 只用乘法 生成数组 B 。根据题目对 B[i] 的定义,可列表格,如下图所示。

根据表格的主对角线(全为 1 ),可将表格分为 上三角 和 下三角 两部分。分别迭代计算下三角和上三角两部分的乘积,即可 不使用除法 就获得结果。

作者:jyd
链接:https://leetcode-cn.com/problems/gou-jian-cheng-ji-shu-zu-lcof/solution/mian-shi-ti-66-gou-jian-cheng-ji-shu-zu-biao-ge-fe/
来源:力扣(LeetCode)

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

总结

以上就是本题的内容和学习过程了,不使用除法乍一看还确实不容易找到答案。

欢迎讨论,共同进步。

;