Scala中硬币更改的StackOverflowError?

J L*_*J L 8 scala

我正在为Scala中的Coin(更改)问题编写递归函数.

我的实现打破了StackOverflowError,我无法弄清楚它为什么会发生.

Exception in thread "main" java.lang.StackOverflowError
    at scala.collection.immutable.$colon$colon.tail(List.scala:358)
    at scala.collection.immutable.$colon$colon.tail(List.scala:356)
    at recfun.Main$.recurs$1(Main.scala:58) // repeat this line over and over
Run Code Online (Sandbox Code Playgroud)

这是我的电话:

  println(countChange(20, List(1,5,10)))
Run Code Online (Sandbox Code Playgroud)

这是我的定义:

def countChange(money: Int, coins: List[Int]): Int =  {

  def recurs(money: Int, coins: List[Int], combos: Int): Int = 
  {    
      if (coins.isEmpty)
          combos
      else if (money==0)
          combos + 1
      else
          recurs(money,coins.tail,combos+1) + recurs(money-coins.head,coins,combos+1)

  }
  recurs(money, coins, 0)
} 
Run Code Online (Sandbox Code Playgroud)

编辑:我刚刚在mix中添加了else if语句:

else if(money<0)
    combos
Run Code Online (Sandbox Code Playgroud)

它摆脱了错误,但我的输出是1500的东西:(我的逻辑有什么问题?

Eas*_*sun 17

以下是基于您的代码的正确解决方案:

def countChange(money: Int, coins: List[Int]): Int = {
  def recurs(m: Int, cs: List[Int], cnt: Int): Int =
      if(m < 0) cnt  //Not a change, keep cnt
      else if(cs.isEmpty) {
        if(m == 0) cnt + 1 else cnt // plus cnt if find a change
      }
      else recurs(m, cs.tail, cnt) + recurs(m-cs.head, cs, cnt)
  recurs(money, coins, 0)
}
Run Code Online (Sandbox Code Playgroud)

无论如何,有一个简短的解决方案(但效率不高,您可以缓存中间结果以使其高效.)

def countChange(m: Int, cs: List[Int]): Int = cs match {
  case Nil => if(m == 0) 1 else 0
  case c::rs => (0 to m/c) map (k => countChange(m-k*c,rs)) sum
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*mov 17

接受的答案中的第一个解决方案有一个冗余的最后一个参数,如Paaro所述,所以我想摆脱它.第二种解决方案使用map了我想要避免的,因为在第1周或Scala课程中我还没有涵盖,我认为你正在服用.此外,正如作者正确指出的那样,第二种解决方案会慢一些,除非它使用一些记忆.最后,Paaro的解决方案似乎有一个不必要的嵌套函数.

所以这就是我最终的结果:

def countChange(money: Int, coins: List[Int]): Int =
  if (money < 0)
    0
  else if (coins.isEmpty)
    if (money == 0) 1 else 0
  else
    countChange(money, coins.tail) + countChange(money - coins.head, coins)
Run Code Online (Sandbox Code Playgroud)

你可以看到,这里不需要括号.

我想知道它是否可以进一步简化.