目录
1. 解法一:时:O(N) ,空:O(N)
2. 解法二:(解法一的空间优化) 时:O(N),空:O(1)
3. 解法三
原题链接:238. 除自身以外数组的乘积 - 力扣(Leetcode)
题目描述:
给你一个整数数组
nums
,返回 数组answer
,其中answer[i]
等于nums
中除nums[i]
之外其余各元素的乘积 。题目数据 保证 数组
nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。请不要使用除法,且在
O(n)
时间复杂度内完成此题。
注意:就算能使用除法,要是数组中出现0,该方法同样会失效。(求出整个数组的乘积,分别除以数组中的每一位)
1. 解法一:时:O(N) ,空:O(N)
构造一个类似前缀和一样的数组,只不过是前缀的积,不妨把他记为 L 数组。不仅如此还需要对后缀数组进行同样的操作,不妨记为 R 数组。其中 L 数组下标为 i 的值表示原数组下标从 [0, i - 1] 的元素乘积,R 数组下标为 i 的值表示原数组下标从 [i + 1, 原数组大小 - 1] 的元素乘积。
对于 L 数组下标为 0 的位置,[ 0, -1 ] 显然不存在,即下标为 0 的位置没有左侧的元素,初始化为1 即可。R 数组同理
然后将相同位置下标的 L 数组的值与 R 数组的值相乘即是该下标对应的最终结果。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int length = nums.size();
vector<int> L(length);
vector<int> R(length);
L[0] = 1;
for(int i = 1; i < length; i++)
L[i] = L[i - 1] * nums[i - 1];
R[length - 1] = 1;
for(int i = length - 2; i >= 0; i--)
R[i] = R[i + 1] * nums[i + 1];
vector<int> answer(length);
for(int i = 0; i < length; i++)
answer[i] = L[i] * R[i];
return answer;
}
};
2. 解法二:(解法一的空间优化) 时:O(N),空:O(1)
返回的数组不计入空间复杂度的计算,我们可以用返回的数组来存解法一的 L 数组,或者 R 数组,然后反向遍历,用一个变量存储另一侧数组元素的乘积即可。
如果返回结果的数组存 L 数组,那么从后往前遍历,用一个变量存储遍历下标的右侧元素的乘积即可。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int length = nums.size();
int left = 1, right = 1;
vector<int> answer(length, 1);
for(int i = 0; i < length; i++)
{
answer[i] *= left;
left *= nums[i];
answer[length - 1 - i] *= right;
right *= nums[length - 1 - i];
}
return answer;
}
};
3. 解法三
既然可以用一个变量来计算一侧元素的乘积,那么用两个变量来计算两侧元素的乘积当然也是可行的。维护两个变量,left 用来计算左侧元素的乘积,right用来计算右侧元素的乘积。在遍历的过程中实时更新 left 和 right 即可。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int length = nums.size();
vector<int> answer(length);
answer[0] = 1;
for(int i = 1; i < length; i++)
answer[i] = answer[i - 1] * nums[i - 1];
int right = 1;
for(int i = length - 1; i >= 0; i--)
{
answer[i] = answer[i] * right;
right *= nums[i];
}
return answer;
}
};