题目:
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.)
思路:给定一个数组,求除了自身之外的其他元素的乘积,乍一看比较简单,可以用全部元素的乘积除以当前元素,问题在于有的元素可能是0,分析有元素是0的情况,如果只有一个元素是0,那么其他元素对应的乘积都是0,而这个为0元素对应的乘积是其他所有元素的乘积。
综上,分三种情况,多于两个元素是0,直接退出,返回全为0的结果res;一个元素是0,只计算该元素对应的值,其他元素对应结果为0;没有元素是0,全部元素乘积除以当前元素。
程序:
class Solution {
public int[] productExceptSelf(int[] nums) {
int[] res=new int[nums.length];
int product=1;//没有元素为0的情况下,计算所有元素的乘积
int zero=0;//计算0的个数
int temp=0;//只有一个元素为0的情况下,记录该index
for(int i=0;i<nums.length;i++){
if(nums[i]==0){
temp=i;
zero++;
if(zero>1)
return res;
}
product*=nums[i];
}
if(zero==1){
res[temp]=1;
for(int i=0;i<nums.length;i++){
if(i==temp)
continue;
res[temp]*=nums[i];
}
return res;
}
for(int i=0;i<nums.length;i++){
res[i]=product/nums[i];
}
return res;
}
}
纳闷medium的题目怎么会这么简单,仔细看了下要求不能用除法,那么对于每个nums[i]来说,对应的乘积是它左边的那部分乘以右边的那部分,然后用两次遍历,分别用res和res2来存储某个元素左边和右边的乘积,比如对于nums[i],res[i]表示这个元素左边所有数字的乘积,res2[i]表示这个元素右边所有元素的乘积,最后乘起来就可以了,注意一下边界。
class Solution {
public int[] productExceptSelf(int[] nums) {
int len=nums.length;
int[] res=new int[len];//用于存储i左边的乘积
int[] res2=new int[len];//用于存储i右边的乘积
int product=1;
int zero=0;
int temp=0;
for(int i=0;i<len;i++){
if(nums[i]==0){
temp=i;
zero++;
if(zero>1)
return res;
}
product*=nums[i];
}
if(zero==1){
res[temp]=1;
for(int i=0;i<len;i++){
if(i==temp)
continue;
res[temp]*=nums[i];
}
return res;
}
res[0]=1;
for(int i=1;i<len;i++){
res[i]=res[i-1]*nums[i-1];
}
res2[len-1]=1;
for(int j=len-2;j>=0;j--){
res2[j]=res2[j+1]*nums[j+1];
}
for(int i=0;i<len;i++){
res[i]=res[i]*res2[i];
}
return res;
}
}
题目中还有一个要求,O(1)的空间复杂度,所以把数组res2用rightproduct代替,rightproduct表示当前元素的右边的元素的乘积,边计算,边直接乘到结果res上。
class Solution {
public int[] productExceptSelf(int[] nums) {
int len=nums.length;
int[] res=new int[len];//用于存储i左边的乘积
int rightproduct=1;//节省空间复杂度,用于存储当前元素右边的乘积
int zero=0;
int temp=0;
for(int i=0;i<len;i++){
if(nums[i]==0){
temp=i;
zero++;
if(zero>1)
return res;
}
}
if(zero==1){
res[temp]=1;
for(int i=0;i<len;i++){
if(i==temp)
continue;
res[temp]*=nums[i];
}
return res;
}
res[0]=1;
for(int i=1;i<len;i++){
res[i]=res[i-1]*nums[i-1];
}
for(int j=len-2;j>=0;j--){
rightproduct*=nums[j+1];
res[j]=res[j]*rightproduct;
}
return res;
}
}