Leetcode238.除自身以外数组的乘积——前缀积与后缀积

我们先来看下题目:

 函数接口:

int* productExceptSelf(int* nums, int numsSize, int* returnSize) 
{

}

(注:nums为数组首地址,numsSize为数组元素个数,returnSize为返回数组中元素的个数)

 我们看到这个题目,相信大多数人脑海中第一个浮现的想法是:

1、遍历数组,算出数组所有元素的乘积。

2、再次遍历数组,用第一步得到的答案分别对数组元素做除,并将结果存入一个新的数组。

      可是题目要求我们不能使用除法 ,这意味着我们只能使用乘法,将数组每个元素以外的所有元素的乘积都计算出来。可是如果数组包含的元素非常多,那么这样计算的时间复杂度将会极大。

我们有没有方法可以降低程序的复杂度呢?这里我们来引入一个方法:求数组的前缀积与后缀积。

  1. 前缀积(Prefix Product)方法:

    • 首先创建一个与原数组相同长度的结果数组,初始化值为1。
    • 从左到右遍历原数组,每次将当前元素与其前一个元素的前缀积相乘,并更新结果数组的值。
    • 最终结果数组中的每个元素即为该位置之前所有元素的乘积。
  2. 后缀积(Suffix Product)方法:

    • 首先创建一个与原数组相同长度的结果数组,初始化值为1。
    • 从右到左遍历原数组,每次将当前元素与其后一个元素的后缀积相乘,并更新结果数组的值。
    • 最终结果数组中的每个元素即为该位置之后所有元素的乘积。

我们了解思路后,下一步就是用代码实现我们的思想:

1、我们首先定义两个数组分别储存计算出的前缀积与后缀积,由于是乘法,我们先将prefix数组第一个元素和suffix数组最后一个元素都初始化为1。(也可以将遍历数组使所有元素都初始化为1)

int prefix[100000];
prefix[0]=1;

int suffix[100000];
suffix[numsSize-1]=1;

举一个例子:数组元素为 {1,2,3,4,5,6} ,当 i = 2时,nums[2] = 3。此时我们需要求除 3 以外其他所有元素的乘积。此时prefix[2]=1*2,suffix[2]=4*5*6。随着 i 的增加,前缀积逐渐增大,后缀积逐渐变小。所以我们数组设计的思路就是:随着下标逐渐增大,前缀积增大,后缀积减小。

2、前缀积(prefix)的计算 :

 for(i = 0;i < numsSize; i++)
 {
     prefix[i+1] = prefix[i] * nums[i];
 }

我们采用累乘的思路求出每个元素的前缀积,并记录下来。

3、 后缀积(suffix)的计算:

for (i = 1; i < numsSize; i++)
{
	suffix[numsSize - 1 - i] = suffix[numsSize - i] * nums[numsSize - i];
}

4、将 每一个元素的前缀积与后缀积相乘 即为除自身以外数组元素的乘积。

     使用malloc函数向内存申请空间,创建一个新数组 arr ,用来返回除自身以外数组元素的乘积。

int *arr = (int *)malloc(numsSize*sizeof(int));

for(i = 0;i < numsSize; i++)
{
    arr[i] = prefix[i] * suffix[i];
}

return arr;
 下面,我们写出完整代码:
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    int prefix[100000]; 
    prefix[0] = 1;

    int suffix[100000]; 
    suffix[numsSize - 1] = 1;

    int* arr = (int*)malloc(numsSize * sizeof(int));

    int i;
    for (i = 0; i < numsSize; i++)
    {
        prefix[i + 1] = prefix[i] * nums[i];
    }

    for (i = 1; i < numsSize; i++)
    {
        suffix[numsSize - i - 1] = suffix[numsSize - i] * nums[numsSize - i];
    }

    for (i = 0; i < numsSize; i++)
    {
        arr[i] = prefix[i] * suffix[i];
    }

    *returnSize = numsSize;
    return arr;
}

 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这题怎么做?!?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值