问题描述
我是 Scala 的新手,想了解递归和尾递归。当我用单行编写程序时,它总是给我 StackOverflow 错误,即使 n=1 -
object Recursion extends App {
def factorial(n: Int): Int = //if (n<=1) 1
n * factorial( n - 1 )
println( factorial( 1 ) )
}
对比
object Recursion extends App {
def factorial(n: Int): Int = (
if (n <= 1) 1
else n * factorial( n - 1 )
)
println( factorial( 8 ) )
}
给出正确的值 - 40320
解决方法
明白了,没有if (n<=1)
,它会无限循环。这就是为什么它永远不会出现并给出此错误的原因。
在通过递归解决的问题中,您必须有一个“分支/条件”来中断递归并返回累积值(也就是弹出堆栈),否则问题理论上永远不会停止;实际上,所有对该函数的调用最终都会重载为堆栈分配的内存(即 StackOverflow 错误)
另请注意,您的函数是递归的,但它不是尾递归。要使其成为尾递归,递归调用必须是最后一步。
要使其尾递归,您必须执行以下操作:
def factorial(n: Int): Int = {
@tailrec
def helper(n: Int,acc: Int): Int = {
if (n == 1) acc
else helper(n-1,n*acc)
}
helper(n,1)
}
就您而言,最后一步是乘法 n*factorial(n-1)
。就我而言,这确实是对自己的一种呼唤。
为了清楚起见,在我的示例中,factorial
不是递归的(尾递归或其他),但内部函数 helper
是尾递归的。