238. 除自身以外数组的乘积
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4]
输出: [24,12,8,6]
提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
进阶:
你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
用前后缀和可解决
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> pre(n);
vector<int> next(n);
vector<int> ret;
pre[0]=nums[0];
next[n-1]=nums[n-1];
for (int i = 1;i<n;i++){
pre[i] = pre[i-1]*nums[i];
}
for(int i =n-2;i>=0;i--){
next[i] = next[i+1]*nums[i];
}
for(int i = 0;i<n;i++){
if(i ==0){
ret.push_back(next[i+1]);
}else if(i==n-1){
ret.push_back(pre[n-2]);
}else{
ret.push_back(pre[i-1]*next[i+1]);
}
}
return ret;
}
};
进阶
思路
尽管上面的方法已经能够很好的解决这个问题,但是空间复杂度并不为常数。
由于输出数组不算在空间复杂度内,那么我们可以将 L 或 R 数组用输出数组来计算。先把输出数组当作 L 数组来计算,然后再动态构造 R 数组得到结果。让我们来看看基于这个思想的算法。
算法
初始化 answer 数组,对于给定索引 i,answer[i] 代表的是 i 左侧所有数字的乘积。
构造方式与之前相同,只是我们试图节省空间,先把 answer 作为方法一的 L 数组。
这种方法的唯一变化就是我们没有构造 R 数组。而是用一个遍历来跟踪右边元素的乘积。并更新数组 answer[i]=answer[i]Ranswer[i]=answer[i]∗R。然后 RR 更新为 R=Rnums[i]R=R∗nums[i],其中变量 RR 表示的就是索引右侧数字的乘积。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> ret(n);
ret[0] = nums[0];
for (int i = 1;i<n;i++){
ret[i] = ret[i-1]*nums[i];
}
int sum = 1;
for(int i = n-1;i>=0;i--){
cout<<sum<<endl;
if(i==n-1){
ret[i]=ret[i-1];
}else if(i==0){
ret[i]=sum;
}else{
ret[i] = ret[i-1]*sum;
}
sum *=nums[i];
}
return ret;
}
};