1-
21## 题目地址
2+
33https://leetcode.com/problems/coin-change/description/
44
55## 题目描述
6+
67```
78You 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.
89
910Example 1:
1011
1112Input: coins = [1, 2, 5], amount = 11
12- Output: 3
13+ Output: 3
1314Explanation: 11 = 5 + 5 + 1
1415Example 2:
1516
@@ -23,11 +24,11 @@ You may assume that you have an infinite number of each kind of coin.
2324## 前置知识
2425
2526- 贪心算法
26-
27- ## 思路
27+ - [ 动态规划] ( https://github.com/azl397985856/leetcode/blob/master/thinkings/dynamic-programming.md )
2828
29+ ## 思路
2930
30- 假如我们把coin逆序排列 ,然后逐个取,取到刚好不大于amout ,依次类推。
31+ 假如我们把 coin 逆序排列 ,然后逐个取,取到刚好不大于 amout ,依次类推。
3132
3233```
3334eg: 对于 [1,2,5] 组成 11 块
@@ -51,7 +52,7 @@ eg: 对于 [1,2,5] 组成 11 块
5152因此结果是 3
5253```
5354
54- 熟悉贪心算法的同学应该已经注意到了,这就是贪心算法,贪心算法更amount尽快地变得更小 。
55+ 熟悉贪心算法的同学应该已经注意到了,这就是贪心算法,贪心算法更 amount 尽快地变得更小 。
5556` 经验表明,贪心策略是正确的 ` 。 注意,我说的是经验表明, 贪心算法也有可能出错。 就拿这道题目来说,
5657他也是不正确的! 比如 ` coins = [1, 5, 11] amout = 15 ` , 因此这种做法有时候不靠谱,我们还是采用靠谱的做法.
5758
@@ -84,58 +85,60 @@ class Solution:
8485 dp[i][j] = dp[i][j - 1 ]
8586
8687 return - 1 if dp[- 1 ][- 1 ] == amount + 1 else dp[- 1 ][- 1 ]
87- ```
88-
89- ** 复杂度分析**
88+ ```
89+
90+ ** 复杂度分析**
91+
9092- 时间复杂度:$O(amonut * len(coins))$
9193- 空间复杂度:$O(amount * len(coins))$
9294
93- dp[ i] [ j ] 依赖于` dp[i][j - 1] ` 和 ` dp[i - coins[j - 1]][j] + 1) ` 这是一个优化的信号,我们可以将其优化到一维,具体见下方。
95+ dp[ i] [ j ] 依赖于` dp[i][j - 1] ` 和 ` dp[i - coins[j - 1]][j] + 1) ` 这是一个优化的信号,我们可以将其优化到一维,具体见下方。
96+
9497## 关键点解析
9598
9699- 动态规划
97100
98101- 子问题
99102
100- 用dp [ i] 来表示组成i块钱 ,需要最少的硬币数,那么
103+ 用 dp [ i] 来表示组成 i 块钱 ,需要最少的硬币数,那么
101104
102- 1 . 第j个硬币我可以选择不拿 这个时候, 硬币数 = dp[ i]
105+ 1 . 第 j 个硬币我可以选择不拿 这个时候, 硬币数 = dp[ i]
103106
104- 2 . 第j个硬币我可以选择拿 这个时候, 硬币数 = dp[ i - coins[ j]] + 1
107+ 2 . 第 j 个硬币我可以选择拿 这个时候, 硬币数 = dp[ i - coins[ j]] + 1
105108
106109- 和背包问题不同, 硬币是可以拿任意个
107110
108111- 对于每一个 dp[ i] 我们都选择遍历一遍 coin, 不断更新 dp[ i]
109112
110113## 代码
111114
112-
113- * 语言支持:JS,C++,Python3
115+ - 语言支持:JS,C++,Python3
114116
115117JavaScript Code:
116- ``` js
117118
118- var coinChange = function ( coins , amount ) {
119- if (amount === 0 ) {
120- return 0 ;
121- }
122- const dp = Array (amount + 1 ). fill ( Number . MAX_VALUE )
123- dp[ 0 ] = 0 ;
124- for ( let i = 1 ; i < dp . length ; i ++ ) {
125- for (let j = 0 ; j < coins .length ; j ++ ) {
126- if (i - coins[j] >= 0 ) {
127- dp[i] = Math . min (dp[i], dp[i - coins[j]] + 1 );
128- }
119+ ``` js
120+ var coinChange = function ( coins , amount ) {
121+ if (amount === 0 ) {
122+ return 0 ;
123+ }
124+ const dp = Array (amount + 1 ). fill ( Number . MAX_VALUE ) ;
125+ dp[ 0 ] = 0 ;
126+ for (let i = 1 ; i < dp .length ; i ++ ) {
127+ for ( let j = 0 ; j < coins . length ; j ++ ) {
128+ if (i - coins[j] >= 0 ) {
129+ dp[i] = Math . min (dp[i], dp[i - coins[j]] + 1 );
129130 }
130131 }
132+ }
131133
132- return dp[dp .length - 1 ] === Number .MAX_VALUE ? - 1 : dp[dp .length - 1 ];
133-
134-
134+ return dp[dp .length - 1 ] === Number .MAX_VALUE ? - 1 : dp[dp .length - 1 ];
135135};
136136```
137+
137138C++ Code:
138- > C++中采用INT_MAX,因此判断时需要加上` dp[a - coin] < INT_MAX ` 以防止溢出
139+
140+ > C++中采用 INT_MAX,因此判断时需要加上` dp[a - coin] < INT_MAX ` 以防止溢出
141+
139142``` C++
140143class Solution {
141144public:
@@ -171,10 +174,10 @@ class Solution:
171174```
172175
173176** 复杂度分析**
177+
174178- 时间复杂度:$O(amonut * len(coins))$
175179- 空间复杂度:$O(amount)$
176180
177-
178181## 扩展
179182
180183这是一道很简单描述的题目, 因此很多时候会被用到大公司的电面中。
0 commit comments