Product of Array Except Self
Two passes — left prefix products into output, then right prefix on the fly multiplying in.
3 min read
array prefix-product
Problem#
Return an array where ans[i] is the product of all nums[j] for j != i. Must run in O(n) without using division.
Examples#
[1,2,3,4]→[24,12,8,6].[-1,1,0,-3,3]→[0,0,9,0,0].
Constraints#
2 <= n <= 10^5.
Approach#
Two passes. First left-to-right: ans[i] = product of everything to the left of i. Then right-to-left: multiply each ans[i] by the running product of everything to its right.
Solution#
class Solution {public: vector<int> productExceptSelf(vector<int>& nums) { int n = nums.size(); vector<int> ans(n, 1); for (int i = 1; i < n; ++i) ans[i] = ans[i - 1] * nums[i - 1]; long long right = 1; for (int i = n - 1; i >= 0; --i) { ans[i] = (int)(ans[i] * right); right *= nums[i]; } return ans; }};func productExceptSelf(nums []int) []int { n := len(nums) ans := make([]int, n) ans[0] = 1 for i := 1; i < n; i++ { ans[i] = ans[i-1] * nums[i-1] } right := 1 for i := n - 1; i >= 0; i-- { ans[i] = ans[i] * right right *= nums[i] } return ans}from typing import List
class Solution: def productExceptSelf(self, nums: List[int]) -> List[int]: n = len(nums) ans = [1] * n for i in range(1, n): ans[i] = ans[i - 1] * nums[i - 1] right = 1 for i in range(n - 1, -1, -1): ans[i] *= right right *= nums[i] return ansfunction productExceptSelf(nums) { const n = nums.length; const ans = new Array(n).fill(1); for (let i = 1; i < n; i++) ans[i] = ans[i - 1] * nums[i - 1]; let right = 1; for (let i = n - 1; i >= 0; i--) { ans[i] *= right; right *= nums[i]; } return ans;}class Solution { public int[] productExceptSelf(int[] nums) { int n = nums.length; int[] ans = new int[n]; ans[0] = 1; for (int i = 1; i < n; i++) ans[i] = ans[i - 1] * nums[i - 1]; int right = 1; for (int i = n - 1; i >= 0; i--) { ans[i] = ans[i] * right; right *= nums[i]; } return ans; }}function productExceptSelf(nums: number[]): number[] { const n = nums.length; const ans: number[] = new Array(n).fill(1); for (let i = 1; i < n; i++) ans[i] = ans[i - 1] * nums[i - 1]; let right = 1; for (let i = n - 1; i >= 0; i--) { ans[i] *= right; right *= nums[i]; } return ans;}Editorial#
Two passes avoid division entirely — important because the array may contain zeros (division would explode). ans doubles as the left-prefix buffer; the right-prefix runs in a single scalar variable.
Complexity#
- Time:
O(n). - Space:
O(1)extra.
Concept revision#
Related#