【问题标题】:Structure to allow @tailrec when multiple recursive calls are invoked调用多个递归调用时允许@tailrec 的结构
【发布时间】:2015-07-12 00:44:13
【问题描述】:

以下逻辑确定整数的组合,其总和为 n,产生最大乘积:

def bestProd(n: Int) = {
  type AType = (Vector[Int],  Long)
  import annotation._
  // @tailrec  (umm .. nope ..)
  def bestProd0(n: Int, accum : AType): AType  = {
    if (n<=1) accum
    else {
      var cmax = accum
      for (k <- 2 to n) {
        val tmpacc = bestProd0(n-k, (accum._1 :+ k, accum._2 * k))
        if (tmpacc._2 > cmax._2) {
          cmax = tmpacc
        }
      }
      cmax
    }
  }
  bestProd0(n, (Vector(), 1))
}

此代码确实有效:

scala> bestProd(11)
res22: (Vector[Int], Long) = (Vector(2, 3, 3, 3),54)

现在@tailrec 不起作用对我来说并不奇怪。毕竟递归调用 not 在尾部位置。是否可以重新制定 for 循环以进行适当的单次调用以实现尾递归?

【问题讨论】:

  • 评论,因为它没有回答你的问题。由于您需要检查所有加起来为 n 的序列,因此首先将它们全部生成,然后使用最大乘积对一个进行像素化 - 并且没有任何可变变量 def bestProd(m:Int) = { def sumTo(n:Int):Seq[Seq[Int]] = Seq(n) +:((for (i &lt;- 1 until n; ps &lt;- sumTo(n-i)) yield i+:ps)); sumTo(m).maxBy(_.product) }
  • 感谢 Paul 提供的替代方案。

标签: scala recursion tail-recursion


【解决方案1】:

我认为如果您试图坚持使用所述算法,这是不可能的。重新思考你可以做这样的事情的方法。

import scala.annotation.tailrec
def bestProd1(n: Int) = {
  @tailrec
  def nums(acc: Vector[Int]): Vector[Int] = {
    if (acc.head > 4)
      nums( (acc.head - 3) +: 3 +: acc.tail )
    else
      acc
  }
  val result = nums( Vector(n) )
  (result, result.product)
}

它得出了相同的结果(据我所知),除了我没有将 4 拆分为 2,2

【讨论】:

  • 所以最高乘积总是(以正则表达式表示) [2|4]?[3]* ?显然情况就是这样,因此您的解决方案确实有效。请考虑投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多