问题描述
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。
来源:力扣(LeetCode)
链接:238 除自身以外数组的乘积
解题思路(思考)
关注点 :(1)不能使用除法
(2)时间复杂度为O(n):表示只需要相应的一次遍历:就可以获得相应的结果
基于上述的思考:(不能使用除法) :因此可以将未选择的元素作为枢纽,将其结果进行相应的区分。从而排除掉当前的元素。
若采用暴力的算法,则是双层循环,跳过当前的元素去计算所有的值。这样的算法实现,时间复杂度为O(n²),与题目所要求的O(n)不符合。因此考虑的思路是去多使用额外的空间,实现空间换时间的操作。
联想到前缀树的思路。使用前缀数组和后缀数组分别记录下当前树的前缀值和后缀值,后面通过遍历数组,进行相应值的相乘,从而得到最终的结果
class Solution {
public int[] productExceptSelf(int[] nums) {
// 选择的该数将其值划分成左边界与右边界:能否考虑使用分治的算法进行处理
//时间的要求为O(N):必然考虑到存在空间换时间的情况
// 维护两个数组,分别表示前缀和后缀(左边界、右边界)
int before [] = new int [nums.length];
int after [] = new int [nums.length];
int result [] = new int [nums.length];
before[0] = 1;
for(int i = 1;i<nums.length;i++){
before[i] = before[i-1] * nums[i-1];
}
//后缀
after[nums.length -1] =1;
for(int i = nums.length-2;i>=0;i--){
after[i]= nums[i+1]* after[i+1];
}
for(int i = 0;i<nums.length;i++){
result [i] = after[i]* before[i];
}
return result;
}
}
问题优化
能否在空间复杂度的情况下进行相应的优化,去提升相应的空间。(等同于前面156:最大子序乘积的思路:类似于滚动数组的方式实现)
将一维数组(前缀和后缀压缩成常数级别的函数 before 以及after )每次计算后立即进行结果的计算,从而降低相应的空间复杂度