【问题标题】:Scala Tail Recursive to Not Tail RecursiveScala尾递归到非尾递归
【发布时间】:2018-03-17 20:07:17
【问题描述】:

这可能是一个奇怪的问题,但是......

问题: 如何将 Scala 中的 tail-recursive 函数转换为 non-tail-recursive 解决方案?

注意:我知道尾递归解决方案在 Scala 中很棒,但我被要求将其更改为非尾递归解决方案。我不知道该怎么做

我在这里有一个尾递归解决方案的代码(至少我希望它是尾递归的,哈哈)

def cubesTailRecur(a: List[Int], acc: List[Int] = List.empty): List[Int] = {
      a match {
        case Nil => acc
        case h :: t if (h%2 == 0) => cubesTailRecur(t, acc)
        case h :: t  => cubesTailRecur(t, acc :+ Math.pow(h, 3).toInt)
      }
    }

我的函数所做的是遍历给定的整数列表并返回一个包含所有奇数立方的新数组。

示例:

    println(cubesTailRecur(List(1, 2, 3, 4, 5, 6, 7)))

    // OUTPUT
    // List(1, 27, 125, 343)

【问题讨论】:

    标签: scala recursion


    【解决方案1】:

    尾递归是一种递归形式,其中递归调用是最后一条指令。不进行尾递归意味着您需要对递归调用的结果进行一些其他计算。

    在您的情况下,您可以删除acc/accumulator 参数并通过递归堆栈执行累加。大致如下,

    def cubesRec(a: List[Int]): List[Int] = a match {
      case Nil => List[Int]()
      case h::t if (h%2 == 0) => cubesRec(t)
      case h::t => Math.pow(h,3).toInt :: cubesRec(t)
    }
    

    【讨论】:

    • 这可行,但有一个问题。它以相反的顺序打印列表。例如:List(1, 27, 125, 343) vs. List(343, 125, 27, 1)
    • 我将如何扭转它?编辑:如何在函数中反转它。我知道如何在打印时反转
    • 您可以使用 Math.pow(h,3).toInt :: cubesRec(t) 在前面添加 Math.pow(h,3).toInt
    • 快速问题:如何同时使用+:::。我刚刚测试了两个
    • ::,也称为 cons,只为列表定义,而 +: 定义为 Seq,这是位通用的。看看this question 了解更多