Day04[26/3/4]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 <= 105-30 <= nums[i] <= 30- 输入 保证 数组
answer[i]在 32 位 整数范围内
进阶:你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)
解题思路
对于一个长度为 n 的数组,你想求 m 下标的结果,是不是都是:
用下标从 0 到 m-1 的乘积,乘上,下标从 m+1 到 n-1 的乘积。
前面这个叫做 前缀乘积 ,后面这个叫做 后缀乘积 。
所以创建好这两个数组,最后做乘法就可以了。
参考知识点:前缀和。
Tips:如果想一直往一个 vector 的开头插入内容,你可以:
- 先把这个
vec反转std::reverse(vec.begin(), vec.end()) - 不断用
vec.push_back(元素)插入内容 - 最后再次反转回来就行
Code
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
class Solution
{
public:
vector<int> productExceptSelf(vector<int> &nums)
{
vector<int> prefix_product{nums[0]}; // 前缀乘积
vector<int> suffix_product{nums.back()}; // 后缀乘积
// 前缀乘积(最后一个元素不用乘)
for (int i = 1; i < nums.size() - 1; i++)
{
prefix_product.push_back(
prefix_product[i - 1] * nums[i]);
}
// 后缀乘积(不需要求到第一个元素)
// 由于头部追加性能太差,所以采用尾部追加之后再反转的策略
for (int i = 1; i < nums.size() - 1; i++)
{
suffix_product.push_back(
suffix_product[i - 1] * nums[nums.size() - i - 1]);
}
reverse(suffix_product.begin(), suffix_product.end());
// 计算结果
// 注意第一个元素和最后一个元素不需要乘法!!!
nums[0] = suffix_product[0];
nums[nums.size() - 1] = prefix_product.back();
for (int i = 1; i < nums.size() - 1; i++)
{
nums[i] = prefix_product[i - 1] * suffix_product[i];
}
return nums;
}
};
int main()
{
// vector<int> nums = {1, 2, 3, 4};
vector<int> nums = {-1, 1, 0, -3, 3};
Solution sol;
sol.productExceptSelf(nums);
cout << endl;
for (auto num : nums)
{
cout << num << ",";
}
cout << endl;
return 0;
}