The 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
Input: nums = [1,2,3,4]
Output: [24,12,8,6]
Input: nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]
Constraints
- 2 <= nums.length <= 10^5
- -30 <= nums[i] <= 30
- The product of any prefix or suffix of
numsis guaranteed to fit in a 32-bit integer.
Follow up: Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)
Brute force solution
func productExceptSelf(_ nums: [Int]) -> [Int] {
let n = nums.count
var res = [Int](repeating: 0, count: n)
for i in 0 ..< n {
var val = 1
for j in 0 ..< n {
if i == j {
continue
}
val *= nums[j]
res[i] = val
}
}
return res
}
Explanation
The brute force solution:
- Iterates through all indices
iin the range from 0 ton(excluded). - Creates a second loop and iterates through all indices
jin the range from 0 ton(excluded). - Checks if
iandjindices are equal; if they are, skips the current iteration to the next one. - Updates
valproperty. - Updates
resproperty by indexiandval. - Returns result.
Time/Space Complexity
- Time complexity: O(n^2)
- Space complexity: O(1)
Solution - 2 - Division
func productExceptSelf(_ nums: [Int]) -> [Int] {
let n = nums.count
var val = 1
var zeroCnt = 0
for num in nums {
if num != 0 {
val *= num
} else {
zeroCnt += 1
}
}
if zeroCnt > 1 {
return [Int](repeating: 0, count: n)
}
var res = [Int](repeating: 0, count: n)
for (i, c) in nums.enumerated() {
if zeroCnt != 0 {
if c != 0 {
res[i] = 0
} else {
res[i] = val
}
} else {
res[i] = val / c
}
}
return res
}
Explanation
Solution - 2:
- Iterates through all elements in input
numsand multipliesvalwithnumif the element is not equal to0; if it is, incrementszeroCnt. - Checks if
zeroCntis more than1; if it is, returns an array with0elements with length ofn, otherwise moves to the next step. - Iterates through
enumeratednumsand checks ifzeroCntis not equal to0; if so, it dividesvalbyc. IfzeroCntis 0, checks ifcdoes not equal0and setsres[i]toval; if it does, sets0tores[i]. - Returns result.
Time/Space Complexity
- Time complexity: O(n)
- Space complexity: O(1)
Solution - 3 - Prefix/Postfix
func productExceptSelf(_ nums: [Int]) -> [Int] {
let n = nums.count
var res = [Int](repeating: 0, count: n)
var prefix = [Int](repeating: 0, count: n)
var suffix = [Int](repeating: 0, count: n)
prefix[0] = 1
suffix[n - 1] = 1
for i in 1 ..< n {
prefix[i] = nums[i - 1] * prefix[i - 1]
}
for i in stride(from: n - 2, to: -1, by: -1) {
suffix[i] = nums[i + 1] * suffix[i + 1]
}
for i in 0 ..< n {
res[i] = prefix[i] * suffix[i]
}
return res
}
Explanation
Solution - 3:
- Initializes
res,prefix, andsuffixarrays. - Updates the first
prefixelement with1. - Updates the last
suffixelement with1. - Iterates from
0ton(excluded); updatesprefix[i]with the product ofnumandprefixelements at indexi - 1. - Iterates in reverse from
n - 2to-1; updatessuffix[i]with the product ofnumandsuffixelements at indexi + 1. - Iterates from
0ton(excluded); updatesres[i]with the product ofprefixandsuffixelements at indexi.
Time/Space Complexity
- Time complexity: O(n)
- Space complexity: O(n)
Solution - 4 - Prefix/Postfix (Optimized)
func productExceptSelf(_ nums: [Int]) -> [Int] {
let n = nums.count
var res = [Int](repeating: 1, count: n)
var prefix = 1
for i in 0 ..< n {
res[i] = prefix
prefix *= nums[i]
}
var postfix = 1
for i in stride(from: n - 1, to: -1, by: -1) {
res[i] *= postfix
postfix *= nums[i]
}
return res
}
Explanation
Solution - 4:
- Iterates through the range of indices from 0 to n (excluded).
- Sets
prefixtores[i]. - Multiplies
prefixwith the element ofnums[i]. - Iterates in reversed order.
- Sets
postfixtores[i]. - Multiplies
postfixwith the element ofnums[i]. - Returns result.
Time/Space Complexity
- Time complexity: O(n)
- Space complexity: O(1)