线性递归 转 尾递归 的过程是怎么得来的??

参考的资料(阮一峰):链接描述

例如:

这里有一个线性递归函数(斐波那契数列)

function f(n) {  if ( n <= 1 ) {return 1};  return f(n - 1) + f(n - 2);
}f(10); // 89

改进=》尾递归

function f(n , ac1 = 1 , ac2 = 1) {  if( n <= 1 ) {return ac2};  return f(n - 1, ac2, ac1 + ac2);
}

f(10) // 89

这是怎么转化得来的??

我现在的感觉是
A过程:无法直接通过线性递归代码转换成尾递归,直观表现就是,没法在看到线性递归代码第一眼就能够不经思考的按照一定的格式转换成尾递归

我更倾向的是一个这样的过程:
B过程:线性递归==>原理剖析==>代码重构==>尾递归

所以,我感到疑惑的是:如果线性递归转换为尾递归的过程如B过程,上述改造后的尾递归函数怎么得来的(实际就是看不懂那个尾递归函数要体现的功能...汗!)?求释疑。如果如A过程,求通用的线性递归转换为尾递归的套路


翻翻过去那场雪
浏览 585回答 1
1回答

慕运维8079593

题主要思路的话,简单说一下我的思路吧,当然每个人可能不一样另外,通用的套路的套路应该是不存在的,只能根据这个递归函数的思路,理解了之后才能做转换以题里的斐波那契数列为例:先把线性递归转换成循环let&nbsp;f&nbsp;=&nbsp;(n)&nbsp;=>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;stack&nbsp;=&nbsp;[1,&nbsp;1]&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(let&nbsp;i&nbsp;=&nbsp;2;&nbsp;i&nbsp;<=&nbsp;n;&nbsp;i++)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack[i]&nbsp;=&nbsp;stack[i&nbsp;-&nbsp;1]&nbsp;+&nbsp;stack[i&nbsp;-&nbsp;2] &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;stack[n] }这里用stack模拟了递归调用中的调用栈,可以看出来,虽然最后只需要stack[n]但在求值过程中,吧stack[0]~stack[n]全部求出并存放在了栈里但实际上并不需要,在求完stack[i]后,stack[i - 2]就没有必要存在了也就是说只需要暂存当前值和上一个求出的值所以可以优化一下let&nbsp;f&nbsp;=&nbsp;(n)&nbsp;=>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;current&nbsp;=&nbsp;1,&nbsp;prev&nbsp;=&nbsp;1 &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(let&nbsp;i&nbsp;=&nbsp;2;&nbsp;i&nbsp;<=&nbsp;n;&nbsp;i++)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;oldCurrent&nbsp;=&nbsp;current&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;current&nbsp;+&nbsp;prev&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;prev&nbsp;=&nbsp;oldCurrent&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;&nbsp;要推出和题例里一样的求值方式的话应该这样写,上面用了一个临时变量更容易理解 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;current&nbsp;+&nbsp;prev &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev&nbsp;=&nbsp;current&nbsp;-&nbsp;prev &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;current }这样就只用到了两个临时变量current和prev,不再需要用到栈了是不是就和尾递归优化所要达到的效果一样了?到这里我觉的应该都能推出对应的尾递归函数了let&nbsp;f&nbsp;=&nbsp;(n,&nbsp;current&nbsp;=&nbsp;1,&nbsp;prev&nbsp;=&nbsp;1)&nbsp;=>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(n&nbsp;<=&nbsp;1)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;current &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;current&nbsp;+&nbsp;prev &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev&nbsp;=&nbsp;current&nbsp;-&nbsp;prev &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;f(n&nbsp;-&nbsp;1,&nbsp;current,&nbsp;prev) &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp; }再简化一下let&nbsp;f&nbsp;=&nbsp;(n,&nbsp;current&nbsp;=&nbsp;1,&nbsp;prev&nbsp;=&nbsp;1)&nbsp;=>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(n&nbsp;<=&nbsp;1)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;current &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;f(n&nbsp;-&nbsp;1,&nbsp;current&nbsp;+&nbsp;prev,&nbsp;current) &nbsp;&nbsp;&nbsp;&nbsp;} }题例里的尾递归优化就出来了(写完才发现和题例里的函数参数顺序搞反了...)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript