LeetCode每日一题 007 除自身以外数组的乘积

1、解题思路


这道题想了半天一直没想出什么好的办法,后来在纸上写写画画,终于找到了一种实现方法。

首先,想的是列个如下的数组出来:

2 4 5 3

4 2 2 2

5 5 4 4

3 3 3 5

第一行每个元素对应的其余元素的乘积 为同列其他元素的乘积,但这样一来求解乘积的复杂度仍是o(n*n)

然后,开始用函数去抽象每个元素的结果,结果用T表示,乘积用S表示,发现T0 = S(1..N-1),,T1=S(0) * S(2..N-1),

方法瞬间就清晰了:只要求出 数组中位于 指定元素K前所有元素的乘积S1(0..K-1) 与 位于该元素后所有元素的乘积S2(K+1...N-1),S1与S2相乘便得到了元素K的题解值TK。那么通过顺序、倒序两次遍历数组,计算乘积,就能得到每个元素前后元素的乘积值,也就得到了要求解的值。

           改进:使用常数空间求解。

           仍是通过计算某元素左右两侧元素乘积来得到求解值,可以发现,求解值T在顺序遍历时即等于左侧元素乘积S1,倒序遍历时等于S1与S2乘积,因为两次遍历是依次进行的,所以可以直接将S1保存到T,再更新T值为S1*S2即可。

           顺序遍历时,TK 可用T(K-1)*A(K-1)表示,A(K)为元素K的值,故不需要中间变量;

           倒序遍历时,TK 可用T(K) * S(K+1...N-1)表示,需要新增局部变量保存右侧元素乘积的值。

2、有效题解


int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    if (NULL == nums || NULL == returnSize)
    {
        return NULL;
    }

    int *ret = (int *)malloc(sizeof(int) * numsSize);
    int *productBefore = (int *)malloc(sizeof(int) *numsSize);
    int *productAfter = (int *)malloc(sizeof(int) *numsSize);

    int i, j;
    productBefore[0] = 1;
    productAfter[numsSize - 1] = 1;
    for (i = 1; i < numsSize; i++)
    {
        productBefore[i] = productBefore[i-1] * nums[i-1];
    }
    for (j = numsSize - 2; j >= 0; j--)
    {
        productAfter[j] = productAfter[j+1] * nums[j+1];
    }

    for (i = 0; i <numsSize; i++)
    {
        ret[i] = productBefore[i] * productAfter[i];
    }

    free(productBefore);
    free(productAfter);

    *returnSize = numsSize;
    return ret;
}

空间优化解

int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    if (NULL == nums || NULL == returnSize)
    {
        return NULL;
    }

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

    int i, j;
    int right = 1;
    ret[0] = 1;
    for (i = 1; i < numsSize; i++)
    {
        ret[i] = ret[i-1] * nums[i-1];
    }

    ret[numsSize-1] *= right;
    for (j = numsSize - 2; j >= 0; j--)
    {
        ret[j] *= right * nums[j+1];
        right = right * nums[j+1];
    }

    *returnSize = numsSize;
    return ret;
}

3、复杂度分析


遍历两次数组,时间复杂度o(n),新增两个数组保存中间值,空间复杂度o(n)。

4、小结


1、通过举例去发现规律,同时结合正向、逆向,一维、多维角度进行摸索。

2、思考使用常数空间求解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值