Leetcode--除自身以外的数组的乘积-【238】

题目:

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请不要使用除法,且在 O(n) 时间复杂度内完成此题

分析:

  • 使用除法(行不通)
    如果一个数组为:[a1,a2,a,3,...,an]; 则answer[i] = a1*..*a(i-1)*a(i+1)*...*an
for(int i =0; i<a.size(); i++){
	Sum_number *= a[i];
}

如果使用除法,则当有0元素时,出现异常, 即:answer[i] = a1*..*ai+1*...*an /ai

for(int i =0; i<a.size(); i++){
	answer[i] = Sum_number / a[i];
}

且题目仅保证其余元素乘积不溢出, 但有可能总乘积溢出。
该方法 时间复杂度为O(N),空间复杂度为O(N)

  • 循环嵌套(超时)
    针对处元素i的其他元素累乘,时间复杂度O(N^2),与题目要求不符,可能会超时。
for(int i=0; i<a.size(); i++){
	answer[i] = 1;
	for(int j=0; j<a.size(); j++){
		if (i!=j){
			answer[i] *=a[j];
		}
	}	
}
  • 前后缀(优化)

题目的难度在于如何用乘法(不涉及除法),且不使用循环嵌套,将时间复杂度降低为O(N)
由于是前缀乘后缀,在顺序遍历时,其实是有规律可循的。

answer[i] = per[i] * after[i]
answer[i+1] = per[i+1] * after[i+1]

其中前后缀关系

per[i+1] = per[i] * nums[i];
after[i] = after[i+1] * nums[i+1];

则per数组的规律为,索引采用0->(n-1)

per[0] = 1; 
per[1] = per[0]*a[0]; 
per[2] = per[1]*a[1] = a[0]*a[1];
per[3] = per[2]*a[2] = a[0]*a[1]*a[2];
...
per[i] = per[i]*a[i-1] = a[0]*a[1]*a[2]*...*a[i-1];
...
per[n-1] = per[n]*a[(n-1)-1] = a[0]*a[1]*a[2]*...*a[(n-1)-1];
----------------------------------------------------- 
after[(n-1)-0] = 1;
after[(n-1)-1] = after[n-1]*a[n-1] = a[n-1];
after[(n-1)-2] = after[n-2]*a[n-2] = a[n-1]*a[n-2]; 
after[(n-1)-3] = after[n-3]*a[n-3] = a[n-1]*a[n-2]*a[n-3]; 
... 
after[(n-1)-i] = after[(n-1)-(i-1)]*a[(n-1)-(i-1)] = a[n-1]*a[n-2]*...*a[(n-1)-(i-1)]; 
...
after[(n-1)-(n-1)] = after[1]*a[1] = a[n-1]*....*a[1];

如此,通过3个数组,则可以避免循环嵌套, 时间复杂度为O(N)
代码:

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> per(n,1);
        vector<int> after(n,1);
        vector<int> answer(n,1);
        
        for(int i = 1; i < n; i++){
            per[i] = per[i-1]*nums[i-1];
            after[n-1-i] = after[n-1 -i+1] * nums[n-1-i+1];
        }

        for(int i=0; i<n ;i++){
            answer[i] = per[i]*after[i];
        }
        return answer;
    }
};

总结:

前缀后缀的思想与模型,利用前后缀变化关系与数组的特性,改善时间复杂度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值