Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].
Solve it without division and in O(n).
For example, given [1,2,3,4], return [24,12,8,6].
Follow up:
Could you solve it with constant space complexity? (Note: The output array does not count as extra space for the purpose of space complexity analysis.)
题中给定一个数组,然后需要计算出除了当前下标位置的其他所有下标位置之积,然后放在当前下标中。也就是例子中的:[1,2,3,4],第一个下标位置存放除了第一个之外的其他所有元素之积,那么就是2*3*4=24,其他下标也是如此,所以得到:[24,12,8,6]。
按照题中的描述,我们只需要将当前元素除去,然后计算其他元素的乘积,再存放到当前元素的下标中即可。
其中一个很好的思路就是循环两次数组,第一次计算每个元素左边的所有数字的乘积存放在当前位置上。然后再反过来从右边开始计算乘积不过从右边的时候需要与自身相乘,这样左边和右边都计算完成之后也就相当于就算了除了自身之后所有的数字乘积。
也就是原数组为:
1 2 3 4
然后开始遍历原数组,每次都要计算出当前元素的左边所有乘积,也就是如果当前位置为3,那么就计算出位置为1和位置为2的乘积存放在下标为3的位置:
那么遍历完成之后得到的数组就是:
1 1 2 6
其中除了第一个位置之外,其他都等于自身左边的所有数字乘积。
然后从右边开始遍历源数组,同样的每次都计算出自身位置的右边所有位置上的数字乘积,然后于自身相乘保存,因为此时自身的数字等于左边的所有数字乘积。
遍历完成之后的数组为:
24 12 8 6
其中除了最右边,其他位置都等于原来的自身乘以右边的所有数字。
C++:
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();//得到数组的总长度
vector<int> result(n);//计算的结果
int left = 1;//从左边开始计算
for(int i=0; i < n; i++) {
if(i > 0) {//从第二个开始
left = left * nums[i-1];//乘以左边的数字得到左边的数字总和
}
result[i] = left;//当前的位置等于左边的数字总和
}
int right = 1;//从右边开始计算
for(int i=n-1; i >= 0; i--) {
if(i < n-1) {//从倒数第二个开始
right = right * nums[i+1];//得到右边的总和
}
result[i] = result[i] * right;//当前位置再乘以右边的总和
}
return result;
}
};