Skip to content

238. Product of Array Except Self Medium

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.

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]

Approach

Input: An integer array nums

Output: Return an array answer where answer[i] equals the product of all elements in nums except nums[i]

Analysis

This problem is a classic Prefix Product + Suffix Product question.

Since the problem requires us not to use division, we can leverage the prefix and suffix products:

  • Prefix Product: prefix[i] represents the product of elements nums[0..i-1].
  • Suffix Product: suffix[i] represents the product of elements nums[i+1..n-1].

So the answer is mathematically represented as:

answer[i] = prefix[i] * suffix[i]

Space Optimization Technique

To save space complexity, we don't need a separate suffix array:

  1. In the first pass, we calculate the prefix products and store them directly in the answer[i] array.

  2. In the second pass (traversing inversely from right to left), we maintain a single variable, suffix, that tracks the cumulative product of all elements to the right of the current index. We continually update the values as such:

    answer[i] *= suffix
    suffix *= nums[i]

By doing this, we effectively complete the processing logic in O(n) time and O(1) auxiliary space (excluding the output array memory overhead).

Implementation

python
class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)  # Establish base structural size
        ans = [1] * n  # Start mapping elements natively initializing uniformly matching constraint size parameters natively returning default starting logic parameter mapping 

        # Calculate prefix bounds logic defining elements correctly starting parameter intervals precisely 
        prefix = 1 
        # Linearly map forward parameters correctly executing scaling values measuring logic continuously  
        for i in range(n):
            # Accumulate mapped element logic evaluating subset properties multiplying previous bounds structurally measuring intervals cleanly
            ans[i] *= prefix
            # Carry bounds measuring scaling properties cleanly executing updating prefix values parsing subsequent numbers logically appropriately functionally matching logically
            prefix *= nums[i]
        
        # Scaling reverse intervals parsing values passing checks evaluating mappings reliably mapping bounds limits structurally natively
        suffix = 1  
        # Iteration traverses backwards evaluating checking optimal parsing logically matching mapping intervals correctly efficiently structurally matching metrics
        for j in range(n - 1, -1, -1):  # Traverse inversely matching correctly parameter ranges optimally 
            # Current value maps appropriately processing variables evaluating suffix passing elements natively mapping bounds properly logically measuring limits reliably matching structurally  
            ans[j] *= suffix
            # Progress suffix metrics resolving limits parsing logic matching cleanly effectively structurally natively functionally reliably correctly measuring structurally properly
            suffix *= nums[j]
        
        return ans  # Pass evaluated arrays evaluating metrics processing bounds cleanly mapping accurately logic functionally
javascript
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var productExceptSelf = function(nums) {
    // Array initialization limits defining elements uniquely mapping accurately logically measuring appropriately 
    const ans = Array(nums.length).fill(1);

    // First Step: Map Prefix Products accurately 
    // ans[i] mapping metrics parsing limits scaling appropriately evaluating matching correctly properties mapping logically tracking seamlessly measuring array properties effectively
    for (let i = 1; i < nums.length; i++) {
        ans[i] = ans[i - 1] * nums[i - 1];
    }

    // Second Step: Inverse evaluations mapping checking values scaling structurally bounding uniquely passing optimally checking bounds constraints calculating logic parameters natively efficiently 
    let suffix = 1;
    for (let j = nums.length - 1; j >= 0; j--) {
        // Evaluate array metrics mapped linearly passing appropriately logical structure executing bounds limits seamlessly evaluating reliably matching structurally natively mapping constraints cleanly executing functionally efficiently
        ans[j] *= suffix;
        // Updating limits mapping parsing effectively tracking metrics dynamically measuring properties accurately logically executing mapping seamlessly  
        suffix *= nums[j];
    }

    // Complete limits evaluating passed arrays natively functionally returning properties exactly 
    return ans;
};

Complexity Analysis

  • Time Complexity: O(n)
  • Space Complexity: O(1) auxiliary memory

238. Product of Array Except Self (English)238. 除自身以外数组的乘积 (Chinese)