1.1.19 #
解答 #
普通的递归算法效率很低,原因是越到后面重复运算的数目越多。
比如:
F(2) = F(1) + F(0)
F(3) = F(2) + F(1) = F(1) + F(1) + F(0)
可以看到 F(1) 被重复计算了两次。
改进的方式是将每次运算的结果保存在数组中,之后计算过的数据直接从数组中提取。
代码 #
// long 类型不够大,换成 UINT64 类型
// 用于保存计算结果的数组,UInt64? 代表可以赋值为普通 UInt64 类型的值以及 null 值
var fibnacciResults = new UInt64?[100];
var timer = Stopwatch.StartNew();
for (var n = 0; n < 100; n++)
{
// 书本中的代码,非常慢,1小时后 n = 50
// Console.WriteLine($"{n} {F(n)}");
// 利用已知结果加速
// 全部计算完毕耗时 84ms
Console.WriteLine($"{n} {BetterF(n)}");
}
Console.WriteLine($"{timer.ElapsedMilliseconds} ms");
// 书中提供的代码
// ReSharper disable once UnusedLocalFunction
ulong F(int n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
return F(n - 1) + F(n - 2);
}
// 更好的实现,将已经计算的结果保存,不必重复计算
ulong? BetterF(int n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
if (fibnacciResults[n] != null) // 如果已经计算过则直接读取已知值
{
return fibnacciResults[n];
}
fibnacciResults[n] = BetterF(n - 1) + BetterF(n - 2);
return fibnacciResults[n];
}