Multiplication of numbers

1. 题目:给定一个整数数组,要求输出一个数组,使新数组的第i位是原数组中除去第i位剩余数字的乘积。如输入{4,3,2,1,2},输出{12,16,24,48,24}。要求时间复杂度为:O(n),且不能使用除法运算。

2. 分析:如果可以使用除法运算很容易想到的算法是将原数组中所有数字相乘,然后遍历,每次除以原数组中的第i位,即得到新数组中的第i位。但是这个算法有一个问题,要是原数组中存在一个数字为0,那么乘积自然也为0,那么新数组中的所有数字都是0,结果不对,而且除以0会导致异常。文章中给出了一个采用O(n)空间的算法,即定义数组B为原数组从左向右相乘的结果{1,4,12,24,24}(第一个数为1,最后一个数为前面4个数相乘)。然后从右向左遍历原数组,将遍历到的数相乘得到p(p初始值为1),过程如下:

  第4个数:B[i]*p=B[4]*p=B[4]*p=24*1=24  p=1   

  第3个数:B[i]*p=B[3]*p=B[3]*p=24*2=48  p=1*2=2

  第2个数:B[i]*p=B[2]*p=B[2]*p=12*2=24  p=1*2*1=2

  第1个数:B[i]*p=B[1]*p=B[1]*p=4*4=16    p=1*2*1*2=4

  第0个数:B[1]*12=12                  p=1*2*1*2*3=12

上面的算法需要O(n)空间,文章中最后给出了常数空间的算法:

 1 void array_multiplication(int A[], int OUTPUT[], int n) { 
 2     int left = 1; 
 3     int right = 1; 
 4     for (int i = 0; i < n; i++) 
 5         OUTPUT[i] = 1; 
 6     for (int i = 0; i < n; i++) { 
 7         OUTPUT[i] *= left; 
 8         OUTPUT[n - 1 - i] *= right; 
 9         left *= A[i]; 
10         right *= A[n - 1 - i];
11         cout<<"OUTPUT["<<i<<"]="<<OUTPUT[i]<<endl;
12         cout<<"OUTPUT["<<n-1-i<<"]="<<OUTPUT[n-1-i]<<endl;
13         cout<<"left="<<left<<endl;
14         cout<<"right="<<right<<endl<<endl;
15     } 
16 }
17 
18 int main()
19 {
20     enum{aLength=5};
21     int a[aLength]={4,3,2,1,2};
22     int output[aLength];
23     array_multiplication(a,output,aLength);
24     for (int i=0;i<aLength;i++)
25     {
26         cout<<output[i]<<"  ";
27     }
28     cout<<endl;
29     return 0;
30 }

3. 对于上面O(1)空间的算法还不是很理解,这样的算法是怎么想到的啊???

4. 参考文章:

http://www.leetcode.com/2010/04/multiplication-of-numbers.html

转载于:https://www.cnblogs.com/ZJUKasuosuo/archive/2012/08/12/2635443.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值