为什么这个递归函数会因堆栈溢出而失败?我怎样才能改进它?

时间:2014-01-21 23:35:18

标签: string scala recursion tail-recursion

我正在考虑在scala中编写一个递归函数,将字符串连接n次。 我的代码如下:

def repeat(s: String, n: Int): String = {
   if(n==1) s
   else 
     s+repeat(s,n-1)
}

我可能没有正确使用“+”吗?但是“+”确实是连接的标志,正如我最初尝试的那样

def repeat(s: String, n: Int): String = {
if(n==1) s
else 
  repeat(s+s,n-1)
 }

重复我的字符串2 ^ n次

3 个答案:

答案 0 :(得分:3)

@annotation.tailrec
final def repeat(s: String, n: Int, ss: String = ""): String = {
    if (n == 0) ss else repeat(s, n - 1, ss + s)
}
repeat("test", 5)

答案 1 :(得分:3)

你的第一个版本不是尾递归。

它必须调用自己,然后然后调用s。对于尾递归,最后一个表达式必须是自调用。这意味着它会使大量值n

的堆栈爆炸

第二个版本尾递归。

@annotation.tailrec置于两个定义之前,编译器将在无法执行尾调用优化的情况下抛出错误。

答案 2 :(得分:0)

一种绕过递归的简单方法,

def repeat(s: String, n: Int) = s * n

因此,

scala> repeat("mystring",3)
res0: String = mystringmystringmystring

此函数可以重写为递归形式,例如如下,

def re(s: String, n: Int): String  = n match {
  case m if (m <= 0) => ""
  case 1 => s
  case m => s + re(s,n-1)
}

请注意+*String运算符的使用情况。