腾讯一道面试题

来源:互联网 发布:仿卷皮淘宝客源码 编辑:程序博客网 时间:2024/06/02 15:56

28)给定一数组a[N],我们希望构造数组b [N],其中b[j]=a[0]*a[1]…a[N-1] / a[j],在构造过程中,不允许使用除法:
要求O(1)空间复杂度和O(n)的时间复杂度;
除遍历计数器与a[N] b[N]外,不可使用新的变量(包括栈临时变量、堆空间和全局静态变量等);
实现程序(主流编程语言任选)实现并简单描述。
先忽略题目所给的任何限制,天马行空想象一下,能想象到什么解法?
1.最简单的办法,将a[0]到a[N-1]全乘起来,再遍历数组,依次除以a[j]即可,这是最简单的办法,但是,不允许使用除法,此法不可行.
2.既然不能使用除法,我们可以换一种思维方式:先将a[j]左边的数全乘一遍,a[j]右边的数全乘一遍,二者再乘起来,就可以避免除法,得到了a[j]的值.这样子,显然要求得每一个a[i]都需要遍历一遍数组,时间复杂度为o(n),求完所有的a[0]到a[N-1],时间复杂度为o(n^2).不符合题意.但是,这个办法给我们提供了一种可能性,那就是,能不能在二层嵌套循环中整合成一层嵌套循环?这个问题暂时不得而知,但是,我们可以知道的是,我们可以实现这个o(n^2)的方法,先实现出来再看看接下来能不能降低时间复杂性.
o(n^2)时间复度性的代码:

void ConstructArray(int* A,int* B,int N){for(int i=0;i<N;++i){B[i]=1;for(int j=0;j<N;++j){if(j != i){B[i]=B[i]*A[j];}}}}

即: | 为分割线.
表:1-1
A[0]=1|*A[1]*A[2]*........*A[N-1]
A[1]=A[0]*|*A[2]*A[3].......A[N-1]
A[2]=A[0]*A[1]*|*A[3]*......A[N-1]
......
A[j]=A[0*A[1]*...A[j-1]|A[j+1]*A[j+2]*...A[N-1]
上面的代码实现思路是这样子的:将问题分为两部分:对于A[0],A[1].....到A[N-1]的每一个A[i],通过一遍的循环遍历数组得出结果.这样子就形
成二层嵌套.
现在,我们需要换一个角度想,能不能将分割线|左右两边的结果全算出来保存在一个数组中,然后,两个数组对应相乘就可以解决问题了.中间,我们不需要两个暂时数组,可以利用B[N]数组的特点来完成这种累积的过程.

void ConstructArray(int* A,int* B,int N){if(!A || !B) return ;B[0]=1;for(int i=0;i<=N-2;++i){B[i+1]=B[i]*A[i];//对比表:1-1容易知道,构造分割线左边部分}//上面已经建立了一个金字塔式的左分割线部分,现在自底向上重复上面的操作就能建立右分割线部分for(int i=N-1;i>=1;--i){B[i]=B[i]*B[0];B[0]=B[0]*A[i];}}

总结:

        题目要求比较苛刻,思维方式是利用B[i]构造左边金字塔型的数组,再构造右边的金字塔型.中间的转换比较巧妙.

原创粉丝点击