理解递归函数
f(n, 0) = 1
f(0, m) = 1
f(n, m) = f(n - 1, m) + f(n, m - 1)
在我看来,这些值就像 Pascal triangle:
n 0 1 2 3 4 ..
m
0 1 1 1 1 1 ..
1 1 2 3 4
2 1 3 6
3 1 4 .
4 1 .
. .
. .
求解递归方程
帕斯卡三角形的值可以表示为binomial coefficients。平移坐标得到 f 的解:
f(n, m) = (n + m)
( m )
= (n + m)! / (m! (n + m - m)!)
= (n + m)! / (n! m!)
这是一个很好的术语,在参数 n 和 m 中都是对称的。 (最终任期首先由@Yves Daoust 在本次讨论中给出)
帕斯卡法则
利用二项式系数的对称性和Pascal's Rule可以推导出f的递归方程
f(n, m) = (n + m)
( n )
= (n + m)
( m )
= ((n + m) - 1) + ((n + m) - 1)
( m ) ( m - 1 )
= ((n - 1) + m) + (n + (m - 1))
( m ) ( m )
= f(n - 1, m) + f(n, m - 1)
确定调用次数
“f 的调用次数”计算函数 F 和 f 类似,我们只需要将 f 本身的调用和两个递归调用相加即可:
F(0, m) = F(n, 0) = 1, otherwise
F(n, m) = 1 + F(n - 1, m) + F(n, m - 1)
(首先由@blubb 在本次讨论中给出)。
了解调用次数函数
如果我们把它写下来,我们会得到另一个三角形方案:
1 1 1 1 1 ..
1 3 5 7
1 5 11
1 7 .
1 .
.
.
逐个比较三角形的值,猜一猜
F(n, m) = 2 f(n, m) - 1 (*)
(@blubb 在本次讨论中首先提出的结果)
证明
我们得到
F(0, m) = 2 f(0, m) - 1 ; using (*)
= 1 ; yields boundary condition for F
F(n, 0) = 2 f(n, 0) - 1
= 1
应该如此并检查 else 子句,我们看到
F(n, m) = 2 f(n, m) - 1 ; assumption
= 2 ( f(n - 1, m) + f(n, m - 1) ) - 1 ; definition f
= 1 + (2 f(n - 1, m) - 1) + (2 f(n, m - 1) - 1) ; algebra
= 1 + F(n - 1, m) + F(n, m - 1) ; 2 * assumption
因此,如果我们使用 (*) 和 f 的 else 子句,则 F 的 else 子句结果。
由于有限差分方程和 F 的起始条件成立,我们知道它是 F(解的唯一性)。
估计调用次数的渐近行为
现在计算/估计 F 的值(即算法的运行时间)。
作为
F = 2 f - 1
我们看到了
O(F) = O(f).
所以这个算法的运行时间是
O( (n + m)! / (n! m!) )
(@Yves Daoust 在本次讨论中首先给出的结果)
近似运行时
使用Stirling approximation
n! ~= sqrt(2 pi n) (n / e)^n
无需难以计算阶乘即可获得表格。一个得到
f(n, m) ~= 1/(2 pi) sqrt((n+m) / (n m)) [(n + m)^(n + m)] / (n^n m^m)
从而到达
O( sqrt((n + m) / (n m)) [(n + m)^(n + m)] / (n^n m^m) )
(@Yves Daoust 在本次讨论中首次建议使用斯特林公式)