- 递归:在函数体中调用函数自身。先执行完所有递归调用(保存了每次调用的状态),用最终拿到的值再往回一步步计算结果。
- 尾递归:调用自身的语句处于函数体中最后一行,仅调用函数自身不包含其它操作。
- 递归的问题:使用少量代码完成需要多次重复的计算,算法逻辑容易理解但效率不高,每递归一次就要开辟一个方法栈(函数空间)保存状态,次数过多消耗性能还可能导致内存溢出。而循环迭代就没有这种问题,使用变量每次接收上次计算的结果,避免反复开辟函数空间。
- 尾递归优化:属于编译期优化,通过 tailrec 关键字修饰,函数符合尾递归便优化,不符合写法则会提醒,消除了内存溢出的担心。由于是最后一行语句,返回后也没有其它操作,不需要保存状态。
1的阶乘:1
2的阶乘:2*1
3的阶乘:3*2*1
4的阶乘:4*3*2*1
5的阶乘:5*4*3*2*1
计算 N 的阶乘:
fun jiecheng(n: BigInteger): BigInteger { //计算阶乘的结果大大超过Long范围,因此使用Biginteger
return if (n == BigInteger.ONE) //1的阶乘结果是1
BigInteger.ONE
else
n * jiecheng(n - BigInteger.ONE) //n的阶乘是:n*(n-1的阶乘)
}
尾递归优化:
tailrec fun youhua(n: BigInteger, result: BigInteger = BigInteger.ONE): BigInteger { //添加关键字修饰,result默认值为1
return if (n == BigInteger.ONE) //乘1等于本身,所以返回结果
result
else
youhua(n - BigInteger.ONE, n * result) //最后一行调用自身,不包含计算
}
本文探讨了递归与尾递归的概念,指出递归虽简洁但效率较低,可能造成内存溢出。通过阶乘计算的例子展示了如何实现尾递归优化,利用tailrec关键字进行编译期优化,减少内存开销。同时,对比了循环迭代与递归在性能上的差异。
263

被折叠的 条评论
为什么被折叠?



