238. Product of Array Except Self
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:
Example 2:
Constraints:
2 <= nums.length <= 105-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.)
Solution:
answer[i] 等于 nums 中除了 nums[i] 之外其余各元素的乘积。换句话说,如果知道了 i 左边所有数的乘积,以及 i 右边所有数的乘积,就可以算出 answer[i]。
于是:
定义 pre[i] 表示从 nums[0] 到 nums[i−1] 的乘积。 定义 suf[i] 表示从 nums[i+1] 到 nums[n−1] 的乘积。 我们可以先计算出从 nums[0] 到 nums[i−2] 的乘积 pre[i−1],再乘上 nums[i−1],就得到了 pre[i],即
pre[i]=pre[i−1]⋅nums[i−1] 同理有
suf[i]=suf[i+1]⋅nums[i+1] 初始值:pre[0]=suf[n−1]=1。按照上文的定义,pre[0] 和 suf[n−1] 都是空子数组的元素乘积,我们规定这是 1,因为 1 乘以任何数 x 都等于 x,这样可以方便递推计算 pre[1],suf[n−2] 等。
算出 pre 数组和 suf 数组后,有answer[i]=pre[i]⋅suf[i]
优化前:
class Solution {
public int[] productExceptSelf(int[] nums) {
int[] result = new int[nums.length];
int[] prefix = new int[nums.length];
prefix[0] = 1;
for (int i = 1; i < nums.length; i++){
prefix[i] = prefix[i-1] * nums[i-1];
}
//[1, 2, 3, 4]
// 1 1 2 6
int[] postfix = new int[nums.length];
postfix[nums.length -1] = 1;
for (int i = nums.length -2; i >= 0; i--){
postfix[i] = nums[i+1] * postfix[i+1];
}
// [1, 2, 3, 4]
// 24 12 4 1
result[0] = postfix[0];
result[nums.length - 1] = prefix[nums.length -1];
for (int i = 1; i < nums.length-1; i++){
result[i] = prefix[i] * postfix[i];
}
return result;
}
}
// TC: O(n)
// SC: O(n)
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] pre = new int[n];
int[] suf = new int[n];
pre[0] = 1;
suf[n - 1] = 1;
for (int i = 1; i < n; i++){
pre[i] = pre[i - 1] * nums[i - 1];
}
for (int i = nums.length - 2; i >= 0; i--){
suf[i] = suf[i + 1] * nums[i + 1];
}
for (int i = 0; i < n; i++){
nums[i] = pre[i] * suf[i];
}
return nums;
}
}
优化:不使用额外空间 先计算 suf,然后一边计算 pre,一边把 pre 直接乘到 suf[i] 中。最后返回 suf。
题目说「输出数组不被视为额外空间」,所以该做法的空间复杂度为 O(1)。此外,这种做法比上面少遍历了一次。
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] suf = new int[n];
suf[n - 1] = 1;
for (int i = n - 2; i >= 0; i--){
suf[i] = suf[i + 1] * nums[i + 1];
}
int pre = 1;
for (int i = 0; i < n; i++){
// 此时pre为nums[0]到nums[i - 1]的乘积, 直接乘到suf[i]中
suf[i] = suf[i] * pre;
pre = pre * nums[i];
}
return suf;
}
}
// 复杂度分析
// 时间复杂度:O(n),其中 n 是 nums 的长度。
// 空间复杂度:O(1)。返回值不计入。