题目描述:
/* * 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请不要使用除法,且在 O(n) 时间复杂度内完成此题。 输入: nums = [1,2,3,4] 输出: [24,12,8,6] 输入: nums = [-1,1,0,-3,3] 输出: [0,0,9,0,0] 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/product-of-array-except-self */
思路:
时间要求为O(n),且不能用除法——空间换时间?遍历过程保存遍历过的数的乘积?
解决方案:
维护乘积数组:维护两个数组L、R,L[i]与R[i]表示数组i除自己外左边乘积或右边乘积。对于头尾元素,L[0]与R[nums.size() - 1]设置为1. L[i] = L[i - 1]与nums[i]的乘积(因为L[i - 1]表示nums[i]左边所有元素的乘积,不包括nums[i])。R[i]同理。
#include<iostream>
#include<vector>
using namespace std;
vector<int> productExceptSelf(vector<int>& nums)
{
//左右数组乘机:维护两个数组L、R,L[i]与R[i]表示除自己nums[i]外左边所有数乘积或右边所有数
//乘积
vector<int> L(nums.size(), 0);
vector<int> R(nums.size(), 0);
L[0] = 1;
for (int i = 1; i < nums.size(); i++)
{
L[i] = L[i - 1] * nums[i - 1];
}
R[nums.size() - 1] = 1;
for (int i = nums.size() - 2; i >= 0; i--)
{
R[i] = R[i + 1] * nums[i];
}
for (int i = 0; i < nums.size(); i++)
{
L[i] *= R[i];
}
return L;
}
时间复杂度为O(n),空间复杂度为O(n).
能否优化?
只需要L数组,对于R数组动态构造,构造过程:
L数组构造完成后,由于没有R数组,从前向后遍历无法得出答案,考虑从后向前
i = nums.size() - 1时,R = 1,L[i] = L[i] * R,更新完L[i]后,更新R,R = R * nums[i]
迭代直至结束。
#include<iostream>
#include<vector>
using namespace std;
vector<int> productExceptSelf(vector<int>& nums)
{
//维护两个数组L,L[i]数组i除自己外左边乘积
vector<int> L(nums.size(), 0);
//优化:空间复杂度优化为O(1) 只使用L数组,对R数组动态构建
for (int i = 1; i < nums.size(); i++)
{
L[i] = L[i - 1] * nums[i - 1];
}
int R = 1;
for (int i = nums.size() - 1; i >= 0; i--)
{
L[i] = L[i] * R;
R *= nums[i];
}
return L;
}