我正在尝试使用递归来编写Scala中的硬币更改问题。我写的代码如下。
def countChange(money: Int, coins: List[Int]): Int = {
def ways(change: List[Int], size: Int, capacity: Int): Int = {
if(capacity == 0) 1
if((capacity < 0) || (size <= 0)) 0
//println and readLine to check and control each recursive call.
println("calling ways(",change, change.length-1, capacity,") + ways(",change, change.length, capacity - change(change.length - 1),")")
readLine()
//
ways(change, change.length-1, capacity) + ways(change, change.length, capacity - change(change.length - 1))
}
ways(coins, coins.length, money)
}
在运行代码时,它不会终止并继续调用第一个递归调用。我哪里错了?
答案 0 :(得分:87)
美好而简单
def countChange(money: Int, coins: List[Int]): Int = {
if(money == 0)
1
else if(money > 0 && !coins.isEmpty)
countChange(money - coins.head, coins) + countChange(money, coins.tail)
else
0
}
答案 1 :(得分:19)
这是我的实施: 我测试了它,它工作正常
def countChange(money: Int, coins: List[Int]): Int = {
def count(capacity: Int, changes: List[Int]): Int = {
if(capacity == 0)
1
else if(capacity < 0)
0
else if(changes.isEmpty && capacity>=1 )
0
else
count(capacity, changes.tail) + count(capacity - changes.head, changes)
}
count(money, coins.sortWith(_.compareTo(_) < 0))
}
答案 2 :(得分:7)
简单地说明一个值不会让Scala返回它;你需要一个明确的回报,或者它必须是最后一个项目。因此:
if (capacity == 0) return 1
或
if (capacity == 0) 1
else if (...)
else { ... }
答案 3 :(得分:7)
只是另一种解决方案
def countChange(amount: Int, coins: List[Int]): Int = coins match {
case _ if amount == 0 => 1
case h :: t if amount > 0 => countChange(amount - h, h :: t) + countChange(amount, t)
case _ => 0
}
答案 4 :(得分:2)
嘿,我只是认为不仅要查看数量而且还要查看它们的列表会更好,所以请将上面的示例放在上面:
def moneyChanges(money: Int, coins: List[Int]) : Option[List[Seq[Int]]]= {
var listOfChange=List[Seq[Int]]()
def changeMoney(capacity: Int, changes: List[Int], listOfCoins: Option[Seq[Int]]): Int = {
if (capacity == 0) {
listOfChange = listOfCoins.get :: listOfChange
1
} else if (capacity < 0)
0
else if (changes.isEmpty && capacity >= 1)
0
else {
changeMoney(capacity, changes.tail, listOfCoins) +
changeMoney(capacity - changes.head, changes,
Some(changes.head +: listOfCoins.getOrElse(Seq())))
}
}
changeMoney(money, coins.sortWith(_.compareTo(_) < 0), None)
Some(listOfChange)
}
答案 5 :(得分:0)
这是一种在递归方法中减少大量重新计算的DP方法
object DP {
implicit val possibleCoins = List(1, 5, 10, 25, 100)
import collection.mutable.Map
def countChange(amount: Int)(implicit possibleCoins: List[Int]) = {
val min = Map((1 to amount).map (_->Int.MaxValue): _*)
min(0) = 0
for {
i <- 1 to amount
coin <- possibleCoins
if coin <= i && min(i - coin) + 1 < min(i)
} min(i) = min(i-coin) + 1
min(amount)
}
def main(args: Array[String]) = println(countChange(97))
}
请参阅DP from novice to advanced了解算法
答案 6 :(得分:0)
下面的代码类似于上面的示例之一,除了我使用匹配大小写而不是if else
def countChange(money: Int, coins: List[Int]): Int = {
def change(m: Int, coinList: List[Int], count: Int): Int =
m match {
case _ if m < 0 => count
case _ if coinList.isEmpty => {
m match {
case 0 => count + 1
case _ => count
}
}
case _ => change(m, coinList.tail, count) + change(m - coinList.head, coinList, count)
}
change(money, coins, 0)
}
答案 7 :(得分:0)
这是我的代码:尚未优化,但适用于所有测试用例。
这个想法是从货币中减去列表中的第一个硬币,直到它变成0。一旦变成0,它将返回1,这意味着一个解决方案是可能的。为了添加来自不同递归的所有解决方案,我使用了foldLeft
。
(使用foldLeft
迭代列表,因此首先进入1,然后再次递归并迭代(1,2)列表)
[4, (1, 2)].
/(1 as cn) \ (2 as cn)
[3, (1, 2)]. [2, (2)]
/(-1) \(-2) \
[2, (1, 2)]. [1, (2)]. [0, (2)]
/.(-1) \(-2)
[1, (1, 2)]. [0, (2)]
/. (-1) \(-2)
[0, (1, 2)]. [-1, (2)]
def countChange(money: Int, coins: List[Int]): Int = coins.foldLeft(0)((accum, cn) =>
(money, cn) match {
case (money, _) if money < 0 => 0
case (0, _) => 1
case (curr_money, curr_coin) => {
val (before_curr_coin, after_curr_coin) = coins.span(_ != curr_coin)
accum + countChange(curr_money - curr_coin, after_curr_coin)
}
})