一、题目描述
给定一个数组 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 A A 数组中的各个元素乘起来,然后去除以 A [ i ] A[i] A[i] 就是 B [ i ] B[i] B[i] 的值。但是本题的难点在于不能使用除法,即需要只用乘法生成数组 B B B。根据题目对 B [ i ] B[i] B[i] 的定义,可列表格,如下图所示
根据表格的主对角线(全为1),可将表格分为上三角和下三角两部分。分别迭代计算下三角和上三角两部分的乘积,即可不使用除法就获得结果。
常规算法流程:
①初始化:数组 l e f t left left、数组 r i g h t right right、数组 r e s res res。其中 l e f t [ 0 ] = 1 left[0] = 1 left[0]=1, r i g h t [ l e n − 1 ] = 1 right[len-1]=1 right[len−1]=1
②计算 B [ i ] B[i] B[i] 的下三角各元素的乘积, l e f t [ i ] = B [ i − 1 ] ∗ l e f t [ i − 1 ] left[i]=B[i-1]*left[i-1] left[i]=B[i−1]∗left[i−1]
③计算 B [ i ] B[i] B[i] 的上三角各元素的乘积, r i g h t [ i ] = B [ i + 1 ] ∗ r i g h t [ i + 1 ] right[i]=B[i+1]*right[i+1] right[i]=B[i+1]∗right[i+1]
④将 l e f t [ i ] × r i g h t [ i ] left[i] \times right[i] left[i]×right[i] 保存在 r e s [ i ] res[i] res[i] 中
⑤返回 r e s res res
改进(优化空间复杂度至O(1)):
①初始化:数组 B B B,其中 B [ 0 ] = 1 B[0] = 1 B[0]=1,辅助变量 t m p = 1 tmp = 1 tmp=1
②计算 B [ i ] B[i] B[i] 的下三角各元素的乘积,直接乘入 B [ i ] B[i] B[i]
③计算 B [ i ] B[i] B[i] 的上三角各元素的乘积,记为 t m p tmp tmp,并乘入 B [ i ] B[i] B[i]
④返回 B B B
案例分析:
复杂度分析:
时间复杂度 O ( N ) \rm{O(N)} O(N):其中N
为数组长度,两轮遍历数组a
,使用O(N)
时间
空间复杂度 O ( 1 ) \rm{O(1)} O(1):变量tmp
使用常数大小额外空间(数组b
作为返回值,不计入复杂度考虑)
三、整体代码
常规算法整体代码如下
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* constructArr(int* a, int aSize, int* returnSize){
*returnSize = aSize;
if(aSize == 0){
return NULL;
}
int* left = (int*)malloc(sizeof(int)*aSize);
int* right = (int*)malloc(sizeof(int)*aSize);
int* res = (int*)malloc(sizeof(int)*aSize);
left[0] = 1;
right[aSize-1] = 1;
for(int i = 1; i < aSize; i++){
left[i] = left[i-1] * a[i-1];
}
for(int i = aSize - 2; i >= 0; i--){
right[i] = right[i+1] * a[i+1];
}
for(int i = 0; i < aSize; i++){
res[i] = left[i] * right[i];
}
return res;
}
运行,测试通过
优化后的算法整体代码如下
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* constructArr(int* a, int aSize, int* returnSize){
*returnSize = aSize;
if(aSize == 0){
return NULL;
}
int* b = (int*)malloc(sizeof(int)*aSize);
b[0] = 1;
int tmp = 1;
for(int i = 1; i < aSize; i++){
b[i] = b[i-1] * a[i-1];
}
for(int i = aSize-2; i >=0; i--){
tmp *= a[i+1];
b[i] *= tmp;
}
return b;
}
运行,测试通过