Skip to content

Commit fc04a9a

Browse files
authoredJul 22, 2023
feat: add solutions to lcci problem: No.08.11 (doocs#1270)
No.08.11.Coin
1 parent 4146655 commit fc04a9a

File tree

7 files changed

+419
-24
lines changed

7 files changed

+419
-24
lines changed
 

‎lcci/08.11.Coin/README.md

+195-8
Original file line numberDiff line numberDiff line change
@@ -37,38 +37,225 @@
3737

3838
**方法一:动态规划**
3939

40+
我们定义 $f[i][j]$ 表示只使用前 $i$ 种硬币的情况下,凑成总金额为 $j$ 的方案数。初始时 $f[0][0]=1$,其余元素都为 $0$。答案为 $f[4][n]$。
41+
42+
考虑 $f[i][j]$,我们可以枚举使用的第 $i$ 种硬币的个数 $k$,其中 $0 \leq k \leq j / c_i$,那么 $f[i][j]$ 就等于所有 $f[i−1][j−k \times c_i]$ 之和。由于硬币的数量是无限的,因此 $k$ 可以从 $0$ 开始取。即状态转移方程如下:
43+
44+
$$
45+
f[i][j] = f[i - 1][j] + f[i - 1][j - c_i] + \cdots + f[i - 1][j - k \times c_i]
46+
$$
47+
48+
不妨令 $j = j - c_i$,那么上面的状态转移方程可以写成:
49+
50+
$$
51+
f[i][j - c_i] = f[i - 1][j - c_i] + f[i - 1][j - 2 \times c_i] + \cdots + f[i - 1][j - k \times c_i]
52+
$$
53+
54+
将二式代入一式,得到:
55+
56+
$$
57+
f[i][j]=
58+
\begin{cases}
59+
f[i - 1][j] + f[i][j - c_i], & j \geq c_i \\
60+
f[i - 1][j], & j < c_i
61+
\end{cases}
62+
$$
63+
64+
最后的答案即为 $f[4][n]$。
65+
66+
时间复杂度 $O(C \times n)$,空间复杂度 $O(C \times n)$,其中 $C$ 为硬币的种类数。
67+
68+
我们注意到,$f[i][j]$ 的计算只与 $f[i−1][..]$ 有关,因此我们可以去掉第一维,将空间复杂度优化到 $O(n)$。
69+
4070
<!-- tabs:start -->
4171

4272
### **Python3**
4373

4474
<!-- 这里可写当前语言的特殊实现逻辑 -->
4575

4676
```python
77+
class Solution:
78+
def waysToChange(self, n: int) -> int:
79+
mod = 10**9 + 7
80+
coins = [25, 10, 5, 1]
81+
f = [[0] * (n + 1) for _ in range(5)]
82+
f[0][0] = 1
83+
for i, c in enumerate(coins, 1):
84+
for j in range(n + 1):
85+
f[i][j] = f[i - 1][j]
86+
if j >= c:
87+
f[i][j] = (f[i][j] + f[i][j - c]) % mod
88+
return f[-1][n]
89+
```
4790

91+
```python
92+
class Solution:
93+
def waysToChange(self, n: int) -> int:
94+
mod = 10**9 + 7
95+
coins = [25, 10, 5, 1]
96+
f = [1] + [0] * n
97+
for c in coins:
98+
for j in range(c, n + 1):
99+
f[j] = (f[j] + f[j - c]) % mod
100+
return f[n]
48101
```
49102

50103
### **Java**
51104

52105
<!-- 这里可写当前语言的特殊实现逻辑 -->
53106

54107
```java
108+
class Solution {
109+
public int waysToChange(int n) {
110+
final int mod = (int) 1e9 + 7;
111+
int[] coins = {25, 10, 5, 1};
112+
int[][] f = new int[5][n + 1];
113+
f[0][0] = 1;
114+
for (int i = 1; i <= 4; ++i) {
115+
for (int j = 0; j <= n; ++j) {
116+
f[i][j] = f[i - 1][j];
117+
if (j >= coins[i - 1]) {
118+
f[i][j] = (f[i][j] + f[i][j - coins[i - 1]]) % mod;
119+
}
120+
}
121+
}
122+
return f[4][n];
123+
}
124+
}
125+
```
55126

127+
```java
128+
class Solution {
129+
public int waysToChange(int n) {
130+
final int mod = (int) 1e9 + 7;
131+
int[] coins = {25, 10, 5, 1};
132+
int[] f = new int[n + 1];
133+
f[0] = 1;
134+
for (int c : coins) {
135+
for (int j = c; j <= n; ++j) {
136+
f[j] = (f[j] + f[j - c]) % mod;
137+
}
138+
}
139+
return f[n];
140+
}
141+
}
142+
```
143+
144+
### **C++**
145+
146+
```cpp
147+
class Solution {
148+
public:
149+
int waysToChange(int n) {
150+
const int mod = 1e9 + 7;
151+
vector<int> coins = {25, 10, 5, 1};
152+
int f[5][n + 1];
153+
memset(f, 0, sizeof(f));
154+
f[0][0] = 1;
155+
for (int i = 1; i <= 4; ++i) {
156+
for (int j = 0; j <= n; ++j) {
157+
f[i][j] = f[i - 1][j];
158+
if (j >= coins[i - 1]) {
159+
f[i][j] = (f[i][j] + f[i][j - coins[i - 1]]) % mod;
160+
}
161+
}
162+
}
163+
return f[4][n];
164+
}
165+
};
166+
```
167+
168+
```cpp
169+
class Solution {
170+
public:
171+
int waysToChange(int n) {
172+
const int mod = 1e9 + 7;
173+
vector<int> coins = {25, 10, 5, 1};
174+
int f[n + 1];
175+
memset(f, 0, sizeof(f));
176+
f[0] = 1;
177+
for (int c : coins) {
178+
for (int j = c; j <= n; ++j) {
179+
f[j] = (f[j] + f[j - c]) % mod;
180+
}
181+
}
182+
return f[n];
183+
}
184+
};
185+
```
186+
187+
### **Go**
188+
189+
```go
190+
func waysToChange(n int) int {
191+
const mod int = 1e9 + 7
192+
coins := []int{25, 10, 5, 1}
193+
f := make([][]int, 5)
194+
for i := range f {
195+
f[i] = make([]int, n+1)
196+
}
197+
f[0][0] = 1
198+
for i := 1; i <= 4; i++ {
199+
for j := 0; j <= n; j++ {
200+
f[i][j] = f[i-1][j]
201+
if j >= coins[i-1] {
202+
f[i][j] = (f[i][j] + f[i][j-coins[i-1]]) % mod
203+
}
204+
}
205+
}
206+
return f[4][n]
207+
}
208+
```
209+
210+
```go
211+
func waysToChange(n int) int {
212+
const mod int = 1e9 + 7
213+
coins := []int{25, 10, 5, 1}
214+
f := make([]int, n+1)
215+
f[0] = 1
216+
for _, c := range coins {
217+
for j := c; j <= n; j++ {
218+
f[j] = (f[j] + f[j-c]) % mod
219+
}
220+
}
221+
return f[n]
222+
}
56223
```
57224

58225
### **TypeScript**
59226

60227
```ts
61228
function waysToChange(n: number): number {
62-
const MOD = 10 ** 9 + 7;
63-
let coins = [1, 5, 10, 25];
64-
let dp = new Array(n + 1).fill(0);
65-
dp[0] = 1;
66-
for (let coin of coins) {
67-
for (let i = coin; i <= n; ++i) {
68-
dp[i] += dp[i - coin];
229+
const mod = 10 ** 9 + 7;
230+
const coins: number[] = [25, 10, 5, 1];
231+
const f: number[][] = Array(5)
232+
.fill(0)
233+
.map(() => Array(n + 1).fill(0));
234+
f[0][0] = 1;
235+
for (let i = 1; i <= 4; ++i) {
236+
for (let j = 0; j <= n; ++j) {
237+
f[i][j] = f[i - 1][j];
238+
if (j >= coins[i - 1]) {
239+
f[i][j] = (f[i][j] + f[i][j - coins[i - 1]]) % mod;
240+
}
241+
}
242+
}
243+
return f[4][n];
244+
}
245+
```
246+
247+
```ts
248+
function waysToChange(n: number): number {
249+
const mod = 10 ** 9 + 7;
250+
const coins: number[] = [25, 10, 5, 1];
251+
const f: number[] = new Array(n + 1).fill(0);
252+
f[0] = 1;
253+
for (const c of coins) {
254+
for (let i = c; i <= n; ++i) {
255+
f[i] = (f[i] + f[i - c]) % mod;
69256
}
70257
}
71-
return dp.pop() % MOD;
258+
return f[n];
72259
}
73260
```
74261

0 commit comments

Comments
 (0)