21、搜狗笔试题:一个长度为 n 的数组 a[0],a[1],...,a[n-1]。现在更新数组的名个元素,即a[0]变为 a[1]到 a[n-1]的积,a[1]变为 a[0]和 a[2]到 a[n- 1]的积,...,a[n-1]为 a[0]到 a[n-2]的积(就是除掉当前元素,其他所有元素的积)。程序要求:具有线性复杂度,且不能使用除法运算符。
解答:
left[i]标示着a[i]之前的乘积,right[i]标示着a[i]之后的乘积,a[i]=left[i]*right[i]。
不过,left的计算从左往右扫的时候得出,right是从右往左扫得出。a[i]=left[i]*right[i]
22、
后 2012年4 月 67 日的腾讯暑期实习生招聘笔试中,出了一道与上述 21 题类似的题,
原题大致如下:
两个数 组 a[N] , b[N] ,其 中 A[N] 的各 个元 素值 已知, 现给 b[i] 赋值 , b[i] =
a[0]*a[1]*a[2]...*a[N-1]/a[i];
要求:
1. 不准用除法运算
2. 除了循环计数值,a[N],b[N]外,不准再用其他任何变量(包括局部变量,全局变量等)
3. 满足时间复杂度O(n),空间复杂度 O(1)。
此题,同上题:
解答:求 b=a[0]*a*...a[i- 1]*a*a[i+1]..*a[N-1]/a ,就是求:a[0]*a[1]*...a[i-1]*a[i+1]..*a[N -1]。
只是我把a[i]左边部分标示为left[i],b[i]右边部分标示为right[i];
实现代码:
#include<iostream> #include<stdio.h> using namespace std; void arrMul(int a[],int out[],int n) { int i; int left=1,right=1; for(i=0;i<n;i++) out[i]=1; for(i=0;i<n;i++) { out[i]*=left;//从0-n,逐个计算其左边值 out[n-1-i]*=right;//从n-0,逐个计算计算其右边值 left*=a[i]; right*=a[n-1-i]; } } //测试 int main() { int i; int a[]={1,2,3,4,5,6};//总乘积720 int p[sizeof(a)/sizeof(int)]; arrMul(a,p,6); for(i=0;i<6;i++) printf("%d ",p[i]); //输出 720 360 240 180 144 120 return 0; }