scala学习:递归/尾递归

递归:

例子4:上台阶

N级台阶,即可每次1步也可每次2步走,共有多少种不同走法

解法:迈出第一步有两种方法,第一步后就是N-1N-2的走法了

def step(n:Int):Int = if (n<=2) n else step(n-1)+step(n-2)

推广:如果每次可走1步或2步或3步,则

def step(n:Int):Int = n match { case 1=>1; case 2=>2; case 3=>4;

case _ =>step(n-1)+step(n-2)+step(n-3) }

尾递归:

定义:函数尾(最后一条语句)是递归调用的函数。

tail-recursive会被优化成循环,所以没有堆栈溢出的问题。

 

线性递归的阶乘:

def nn1(n:Int):BigInt = if (n==0) 1 else nn1(n-1)*n

println(nn1(1000)) // 4023...000

println(nn1(10000)) // 崩溃:(

 

尾递归的阶乘:

def nn2(n:Int, rt:BigInt):BigInt = if (n==0) rt else nn2(n-1, rt*n)

println(nn2(1000,1)) // 40...8896

println(nn2(10000,1)) // 2846...000

 

def nn3(n:Int):BigInt = nn2(n,1)

 

对比:

线性递归

尾递归

nn1(5) 
{5 * nn1(4) }
{5 * {4 * nn1(3) }}
{5 * {4 * {3 * nn1(2) }}}
{5 * {4 * {3 * {2 * nn1(1) }}}}
{5 * {4 * {3 * {2 * 1}}}}
{5 * {4 * {3 * 2}}}
{5 * {4 * 6}}
{5 * 24}
120

nn2(5, 1)
nn2(4, 1*5=5)
nn2(3, 4*5=20)
nn2(2, 3*20=60)
nn2(1, 2*60=120)
120

不算,直到递归到一个确定的值后,又从这个具体值向后计算;更耗资源,每次重复的调用都使得调用链条不断加长. 系统使用栈进行数据保存和恢复

每递归一次就算出相应的结果。

不能优化成循环

可以优化成循环


你可能感兴趣的:(scala,递归,尾递归)