题目描述
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。
你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
样例描述
示例:
输入: [1,2,3,4]
输出: [24,12,8,6]
思路
前后缀分解
- 预处理一个前缀数组,记录每个数的前面所有数的乘积。
- 另外一个后缀数组记录这个数后面所有数的乘积,这个数对应的乘积就是前缀乘以后缀积。
由于只能开一个数组,所以后缀乘积要在求的过程中来不断乘当前数递推出来。 为了方便递推要从后往前推。 - 递推求结果时,在把结果放到前缀和乘积中,因为只能开一个数组。
代码
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int p[] = new int[n];
//由于是算乘积,先都初始化为1
Arrays.fill(p, 1);
//计算前缀和乘积 p[i]表示第i个数前面所有数的乘积
for (int i = 1; i < n; i ++ ) {
p[i] = p[i - 1] * nums[i - 1];
}
//递推求后缀和乘积,同时将结果放到前缀和数组中
//从后往前,因为要递推后缀和乘积,末尾的初始为1
for (int i = n - 1, subfixS = 1; i >= 0; i --) {
//当前数的乘积结果等于 前缀和乘后缀和
p[i] = p[i] * subfixS;
//更新后缀和
subfixS *= nums[i];
}
return p;
}
}