package LeetCode_322
/**
* 322. Coin Change
* https://leetcode.com/problems/coin-change/description/
*
* You are given coins of different denominations and a total amount of money amount.
* Write a function to compute the fewest number of coins that you need to make up that amount.
* If that amount of money cannot be made up by any combination of the coins, return -1.
Example 1:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3
Output: -1
Note:
You may assume that you have an infinite number of each kind of coin.
* */
class Solution {
private var array: IntArray? = null
fun coinChange(coins: IntArray, amount: Int): Int {
//init array with amount + 1, then we can use it conveniently
array = IntArray(amount + 1, { 0 })
return dfs(coins, amount)
}
/*
* solution: recursion + memorization (Top-Down), Time complexity:O(amount*amount), Space complexity:O(amount+1)
* */
private fun dfs(coins: IntArray, target: Int): Int {
if (target < 0) {
return -1
}
if (target == 0) {
//match the amount, mean no more coin to add
return 0
}
if (array!![target] != 0) {
return array!![target]
}
var min = Int.MAX_VALUE
for (coin in coins) {
val sub = dfs(coins, target - coin)
if (sub >= 0 && sub < min) {
//+1, just mean we had used 1 coin
min = 1 + sub
}
}
array!![target] = if (min == Int.MAX_VALUE) -1 else min
return array!![target]
}
/*
solution 2: dp (Bottom-Up)
* */
private fun dp(coins: IntArray, amount: Int): Int {
val dp = IntArray(amount + 1, { amount + 1 })
//mean that i can use zero coin to sum up 0
dp[0] = 0
for (i in 0..amount) {
for (coin in coins) {
if (i >= coin) {
//dp[i - coin] + 1, i used that coin
dp[i] = Math.min(dp[i], dp[i - coin] + 1)
}
}
}
return if (dp[amount] > amount) -1 else dp[amount]
}