目录
刷题日期:下午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;
}
}
总结
以上就是本题的内容和学习过程了,不使用除法乍一看还确实不容易找到答案。
欢迎讨论,共同进步。