1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Coin Change [leetcode: coin_change](https://leetcode.com/problems/coin-change/)
//!
//! 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`.
//!
//! ***Example1:***
//!
//! ```
//! Input: coins = [1, 2, 5], amount = 11
//! Output: 3
//! Explanation: 11 = 5 + 5 + 1
//! ```
//!
//! ***Example2:***
//!
//! ```
//! Input: coins = [2], amount = 3
//! Output: -1
//! ```
//!
//! **Note:**
//! You may assume that you have an infinite number of each kind of coin.
//!

/// # Solutions
///
/// # Approach 1: Dynamic Programming
///
/// * Time complexity: O(s*n)
///
/// * Space complexity: O(s)
///
/// * Runtime: 4 ms
/// * Memory: 3 MB
///
/// ```rust
/// impl Solution {
///     pub fn coin_change(coins: Vec<i32>, amount: i32) -> i32 {
///         let mut dp = vec![amount + 1; (amount + 1) as usize];
///         dp[0] = 0;
///
///         for i in 1..=amount {
///             for &coin in coins.iter() {
///                 if i >= coin {
///                     dp[i as usize] = i32::min(dp[i as usize], dp[(i - coin) as usize] + 1);
///                 }
///             }
///         }
///         let last = *dp.last().unwrap();
///         if last > amount { return -1; } else { return last; }
///     }
/// }
/// ```
///
/// # Approach 2: Dynamic Programming
///
/// * Time complexity: O(s*n)
///
/// * Space complexity: O(s)
///
/// * Runtime: 4 ms
/// * Memory: 4 MB
///
/// ```rust
/// impl Solution {
///     pub fn coin_change(coins: Vec<i32>, amount: i32) -> i32 {
///         let mut dp = vec![-1; (amount+1) as usize];
///         dp[0] = 0;
///
///         for i in 1..=amount as usize {
///             dp[i] = std::i32::MAX;
///             for &coin in coins.iter() {
///                 if i >= coin as usize && dp[i - coin as usize] != -1 {
///                     dp[i] = i32::min(dp[i], dp[i - coin as usize] + 1);
///                 }
///             }
///             if dp[i] == std::i32::MAX { dp[i] = -1; }
///         }
///         *dp.last().unwrap()
///     }
/// }
/// ```
///

pub fn coin_change(coins: Vec<i32>, amount: i32) -> i32 {
    let mut dp = vec![amount + 1; (amount + 1) as usize];
    dp[0] = 0;

    for i in 1..=amount {
        for &coin in coins.iter() {
            if i >= coin {
                dp[i as usize] = i32::min(dp[i as usize], dp[(i - coin) as usize] + 1);
            }
        }
    }
    let last = *dp.last().unwrap();
    if last > amount { return -1; } else { return last; }
}