每日一题---238,除自身以外数组的乘积(Leetcode)

题目链接

Leetcode.238

题目描述

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例 1:

输入:

nums = [1,2,3,4]

输出:

[24,12,8,6]

示例 2:

输入:

nums = [-1,1,0,-3,3]

输出:

[0,0,9,0,0]

提示:

2 <= nums.length <= 10^5
-30 <= nums[i] <= 30 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内

进阶:你可以在 O(1) 的额外空间复杂度内完成这个题目( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)

超时的方法

两个for循环,而题目的0=<nums.length<=10^5,所以肯定会超时

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int a=nums.size();
        vector<int> v(a, 1);
        for(int i=0; i<a; i++){
            for(int j=0; j<a; j++){
                if(j!=i)
                    v[i]*=nums[j];
            }
        }
        return v;
    }
};

法1

首先题目说不能使用除法,我们如果使用了除法会怎么样呢,通过了哈哈

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int a=nums.size();
        vector<int> v(a, 1);
        int b=1;
        for(int i=0; i<a; i++){
            b*=nums[i];
        }
        for(int i=0; i<a; i++){
            if(nums[i]!=0)
                v[i]=b/nums[i];
            else{
                for(int j=0; j<a; j++)
                if(j!=i)
                    v[i]*=nums[j];
            }
        }
        return v;
    }
};

法2

注意这里的vlr[i]指的是前i项的乘积,
vrl[j]指的是第j项开始所有往后的项的乘积。
主要思想来源于超时的方法,首先要知道为什么超时,就是因为有太多的重复计算了,我们现在就要通过另外两个数组把乘积先存起来,这样就不会重复计算了,乘积只计算了一次

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int a=nums.size();
        vector<int> v(a, 1);
        int b=1;
        vector<int> vlr(a+1, 1);
        vector<int> vrl(a+1, 1);
        vlr[0]=nums[0];
        vrl[a-1]=nums[a-1];
        for(int i=1; i<a; i++){
            vlr[i]=vlr[i-1]*nums[i];
        }
        for(int j=a-1; j>=0; j--){
            vrl[j]=vrl[j+1]*nums[j];
        }
        for(int i=0; i<a; i++){
            if(i==0){
                v[i]=vrl[i+1];
            }
            else if(i==a-1){
                v[i]=vlr[i-1];
            }
            else{
                v[i]=vlr[i-1]*vrl[i+1];
            }
        }
        return v;
    }
};

法3

题目最后面还有一个进阶的描述,空间复杂度是O(1),而且说输出数组不算入时间复杂度。这样的话我们就利用一下输出的数组:先让它存储上一种方法中的vlr,然后再来一个逆向的循环,让r存储上一种方法中的vrl,就好了。

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int a=nums.size();
        vector<int> v(a, 1);
        int b=1;
        for(int i=1; i<a; i++){
            v[i]=v[i-1]*nums[i-1];
        }
        int r=1;
        for(int j=a-1; j>=0; j--){
            v[j]=v[j]*r;
            r*=nums[j];
        }
        return v;
    }
};

希望大家在看到我的解释之后能够直接了解,同时如果有错误的话请指出,共勉。
一起努力

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

夜猫程序猿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值