logseq_notes/pages/OJ notes/pages/Leetcode Product-of-Array-Except-Self.md
2023-06-14 14:27:22 +08:00

3.4 KiB

  • Leetcode Product-of-Array-Except-Self

    2022-09-05 14:27

    Algorithms:

    #algorithm #prefix_sum

    Data structures:

    #DS

    Difficulty:

    #coding_problems #difficulty_medium

    Additional tags:

    #leetcode #CS_list_need_understanding

    Revisions:

    Mar 28th, 2023 14:09 Mar 30th, 2023 08:01

Problem

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].

The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

You must write an algorithm that runs in O(n) time and without using the division operation.

Examples

Example 1:

Input: nums = [1,2,3,4] Output: [24,12,8,6]

Example 2:

Input: nums = [-1,1,0,-3,3] Output: [0,0,9,0,0]

Constraints

  • 2 <= nums.length <= 105
  • -30 <= nums[i] <= 30
  • The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

Thoughts

[!summary] This is a variation of #prefix_sum

I thought of using prefix product, a variation of prefix_sum, which perfectly fits the requirement.

First iteration:

keep two arrays: the suffix product and the prefix product of the nums array.

Then, ans = prefix[i] * suffix[i]

Second iteration:

It's like rolling snowball, the suffix sum variable gets reused

We can use only one output array:

write the prefix to the ans array, and update it from end using suffix sum variable.

This achieves the O(1) space except output requirement.

Third iteration:

Since the multiplying process is independent, and can be reversed, We can do that in one loop.

1 * A * B == 1 * B * A

If we initialize the ans array as one, we can do that in one loop.

Solution

Third version:

class Solution {
public:
vector<int> productExceptSelf(vector<int> &nums) {
// Optimized one-pass prefix sum & suffix sum
int size = nums.size();

vector<int> ans(size, 1);

int prefix = 1, suffix = 1;

for (int i = 0; i < size; i++) {
ans[i] *= prefix;
prefix *= nums[i];

ans[size - i - 1] *= suffix;
suffix *= nums[size - i - 1];
}

return ans;
}
};

Second version:

class Solution {
public:
vector<int> productExceptSelf(vector<int> &nums) {
// Optimized prefix sum & suffix sum
int size = nums.size();
vector<int> ans(size);

ans[0] = 1;
for (int i = 1; i < size; i++) {
ans[i] = ans[i - 1] * nums[i - 1];
}

int suffix = 1;

for (int i = size - 1; i >= 0; i--) {
ans[i] = ans[i] * suffix;
suffix = suffix * nums[i];
}

return ans;
}
};

First iteration:

class Solution {
public:
vector<int> productExceptSelf(vector<int> &nums) {
// method 1: prefix sum & suffix sum
vector<int> ans;
vector<int> suffix;
int size = nums.size();
ans.resize(size);
suffix.resize(size);

ans[0] = 1;
for (int i = 1; i < size; i++) {
ans[i] = ans[i - 1] * nums[i - 1];
}

suffix[size - 1] = 1;
for (int i = size - 2; i >= 0; i--) {
suffix[i] = suffix[i + 1] * nums[i + 1];
}

for (int i = 0; i < size; i++) {
ans[i] = ans[i] * suffix[i];
}

return ans;
}
};