参考代码:
class Solution {
public int[] productExceptSelf(int[] nums) {
if (nums == null || nums.length == 0) {
return new int[0];
}
int len = nums.length;
int[] res = new int[len];
int left = 1;
for (int i = 0; i < len; i++) {
if (i > 0) {
left = left * nums[i - 1];
}
res[i] = left;
}
int right = 1;
for (int i = len - 1; i >= 0; i--) {
if (i < len - 1) {
right = right * nums[i + 1];
}
res[i] *= right;
}
return res;
}
}
大致思路:左向加右向,来回遍历。
根据题目的要求,常规想法两层for循环的解法不可取,会超出时间限制。
原数组: [2 2 3 4]
左部分的乘积: 1 2 2*2 2*2*3
右部分的乘积: 2*3*4 3*4 4 1
结果: 1*2*3*4 2*3*4 2*2*4 2*2*3*1
这种解法需要注意的是左部分乘积的第一个数必须是一(因为乘以1不会改变最终的结果),这样的话再乘以右部分的乘积才是刚好正确的,而不会多乘以原数组的第一个数。因此用 if (i > 0) 条件限制一下,当i等于0时,不会进入if语句,直接让res[i]=left(=1),当i>0时利用累乘,且因为跳过了一个nums[0]未乘,累乘时应乘以nums[i-1],这样可以保证累乘的都是在nums[i]左边的数;
同理右边也是如此,不过应该从nums[len-1]开始,从右往左乘,累乘时不再是乘以nums[i-1],而是nums[i+1]。
总的思路就是num[i]的左边的数乘以右边的数正好不包括nums[i]。至于第一个数为什么是1,其实累乘往后移一位你会发现才是num[i]的左边的数相乘,相当于填补了2*2*3*4的空位,因为我们不需要这一乘积。
这题的解法有些绕,需要反复琢磨。