Hot100-Day04-T238除了自身以外数组的乘积

3 阅读2分钟

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 的开头插入内容,你可以:

  1. 先把这个 vec 反转 std::reverse(vec.begin(), vec.end())
  2. 不断用 vec.push_back(元素) 插入内容
  3. 最后再次反转回来就行

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;
}