最近很忙,是在木有时间上来写技术博客了。人又变懒了啊~
今天抽点时间,上来讨论一道google的面试题吧~
题目是:给你一个数组 A [ 1 .. n ] ,请你在 O ( n ) 的时间里构造一个新的数组 B [ 1 .. n ] ,使得 B [ i ] = A [ 1 ] * A [ 2 ] * ... * A [ n ]/A [ i ] 。你不能使用除法运算。
思路和解答:这一题实则很简单。有过基本编程思维训练的人都知道,降低时间复杂度,肯定会在空间上有所牺牲。并且,这种类型的题目,最重要的就是要避免重复计算,即必须用额外的空间来储存已经计算得到的记过。这点和尾递归的优化以及动态规划思想有类似之处。
实际上,因为B [ i ] = A [ 1 ] * A [ 2 ] * ... * A [ n ]/A [ i ]
换一种写法,即B [ i ] = A [ 1 ] * ... * A [ i - 1 ] * A [ i + 1 ] * ... * A [ n ]
可以看到上述式子分为两个部分,前半部分是1到i-1的乘积,后者是i+1到n的乘积。
那么我们就可以设置两个数组:
S [ i ] = A [ 1 ] * ... * A [ i – 1 ]
T [ i ] = A [ i + 1 ] * ... * A [ n ]
容易看到
S [ i ] = S [ i-1 ] * A [ i-1 ]
T [ i ] = T [ i + 1 ] * A [ i+1 ]
构造这两个数组所化的时间为o ( 2n )。
其中S是从前往后累乘构造,T是从后往前累乘构造。
之后利用B [ i ] = S [ i ] * T [ i ] ( 2 <= i <= n-1),数组对应的数相乘即可。
实际编码过程中需注意
B [ 1 ] = T [ 1 ];
B [ n ] = S [ n ];
可以分别在T数组和S数组的开头和结尾增补一个数据,即S [1] = 1. T[ n ] = 1
这时,B [ i ] = S [ i ] * T [ i ] ( 1 <= i <= n),
时间复杂度退化为线性,但空间也增至o( 3n )。
以上便是全部解答,希望有帮助!