裴波那契数列
今天看到一个有趣的数列
1,1,2,3,5,8,13,21....
看这组竖列的特征,我们可以看出从第三个开始,第n个的值登月第n-1个加上第n-2个的值。
其实这就是世界上著名的裴波那契数列
好了,现在我们知道了竖列的规律。假如我想知道第40个的值是多少,小伙伴们有什么解决方案了。
最简单的方式:一个个加上去,呵呵40个很快就出来了
但是,作为程序员哥哥,是不会用这么愚蠢的方式的
转入正题,程序员哥哥要开始工作了。
这不是很简单吗,一个递归算法就搞定了
1 public long Calc(long n){ 2 if (n < 1) { throw new IndexOutOfRangeException("n为正整数"); }
if(n==1||n==2){return 1;} 3 return Calc(n-1)+Calc(n-2); 4 }
调用Calc(40);OK,得到值102334155。程序员哥哥很开心的迅速算出了答案。
接下来,有个同学反映说,我想知道更多一点,第100个吧!
程序员哥哥Calc(100);然后就呵呵了,结果是System.StackOverflowException;瞬间在风中凌乱了.....
从结果我们可以很明显看出,这个是栈溢出异常导致的。那么为什么为出现这种情况呢?
我们来看下Calc方法,当n很大的时候,Calc中会嵌套很多的Calc的递推函数,所以就呵呵了.....
既然我们发现了问题的所在,那么就要找到一个解决方案
1 public class FeiBoNaQiShuLie 2 { 3 public IDictionary<long, long> dicShuLie { get; set; } 4 long max = 0; 5 public FeiBoNaQiShuLie(long n) 6 { 7 if (n < 1) { throw new IndexOutOfRangeException("n为正整数"); } 8 dicShuLie = new Dictionary<long, long>(); 9 max = n; 10 for (long i = 1; i <= n; i++) 11 { 12 Calc(i); 13 } 14 } 15 private long Calc(long n) 16 { 17 if (n > 2) 18 { 19 return CacheCalcValue(n - 1) + CacheCalcValue(n - 2); 20 } 21 return 1; 22 } 23 private long CacheCalcValue(long n) 24 { 25 long last; 26 if (dicShuLie.ContainsKey(n)) 27 { 28 last = dicShuLie[n]; 29 } 30 else 31 { 32 last = Calc(n); 33 dicShuLie[n] = last; 34 } 35 return last; 36 } 37 public long Value(long n) 38 { 39 if (n > max) { throw new IndexOutOfRangeException("n 不能超过" + max); } 40 return dicShuLie[n]; 41 } 42 }
看代码可以看出,在FeiBoNaQiShuLie类中,增加了一个字典用于保存Calc计算处理啊的值。
在某种程度上解决了刚才的问题。
但这里又有其他的瓶颈,包括字典的存储容量。如果n过大,初始化工作要好久,这里面有性能的问题,还可以继续优化
具体的,就先写到这里了...优化的工作,后面有空再补充。
我贴出这个代码,不过是为了提供一个解决问题的思路而已。