【问题标题】:How to optimize Scala double Call of Recursive Function如何优化递归函数的Scala双重调用
【发布时间】:2017-07-31 16:07:32
【问题描述】:

我正在尝试让这个递归函数工作:

@tailrec
def rec(n: BigInt): BigInt = {
  if (n == 0) 0
  else if (n == 1) 1
  else (rec(n - 1) + rec(n - 2))
}

错误:(13, 24) 无法优化@tailrec 注释方法rec: 它包含一个不在尾部位置的递归调用 否则 (rec(n - 1) + rec(n - 2))

如何优化它以使用 tailrec?

【问题讨论】:

    标签: scala recursion tail-recursion


    【解决方案1】:

    您将不得不编写一个尾递归辅助函数:

    def rec(n: BigInt): BigInt = {
      @tailrec 
      def helper(n: BigInt, previous: BigInt, next: BigInt): BigInt = {
        if (n == 0) previous
        else if (n == 1) next
        else helper(n - 1, next, (next + previous))
      }
      helper(n,0,1)
    }
    

    这样,您可以将序列的上一个和下一个值传递给函数,从而只允许您对函数进行一次调用。

    这是一种常见的模式,因为许多递归算法只能通过额外的控制流机制(例如:继续传递)进行尾递归。 阶乘是另一个很好的例子,需要编写一个带有额外参数的辅助函数来使其尾递归。

    【讨论】:

    • 让我补充一点,一般来说,尾递归(辅助)方法将始终如下所示: def helper(r: Result, w: Work) 其中 Result 和 Work 类型被选择为适合你的问题。在这种情况下,Result 是 BigInt,Work 是 (BigInt,BigInt)。显然,您可以像 Luka 那样对 Work 进行 untuple,但这不会改变基本思想。如果您有快速返回条件,或者需要进行其他一些特殊处理,它可能会变得更复杂一些,但通常情况下,它看起来像这样。
    猜你喜欢
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    相关资源
    最近更新 更多