1+ class Solution :
2+ def coinChange (self , coins : list [int ], amount : int ) -> int :
3+ dp = [float ('inf' )] * (amount + 1 )
4+ dp [0 ] = 0
5+
6+ for coin in coins :
7+ for x in range (coin , amount + 1 ):
8+ dp [x ] = min (dp [x ], dp [x - coin ] + 1 )
9+
10+ return dp [amount ] if dp [amount ] != float ('inf' ) else - 1
11+
12+ """
13+ ================================================================================
14+ 풀이 과정
15+ ================================================================================
16+
17+ [1차 시도] 완전 탐색으로 접근하면?
18+ ────────────────────────────────────────────────────────────────────────────────
19+ 1. 모든 동전 조합을 시도해보면 어떨까?
20+ 2. coins = [1, 2, 5], amount = 11
21+ - 5 + 5 + 1 = 11 (3개)
22+ - 5 + 2 + 2 + 2 = 11 (4개)
23+ - 1 + 1 + ... (11개)
24+ ... 너무 많은 경우의 수!
25+
26+ 3. 문제: 시간복잡도가 너무 높음 (지수 시간)
27+ 4. 더 효율적인 방법이 필요함 → DP로 접근하자!
28+
29+ ────────────────────────────────────────────────────────────────────────────────
30+ [2차 시도] DP 초기화와 점화식
31+ ────────────────────────────────────────────────────────────────────────────────
32+ 5. dp[i] = i원을 만드는데 필요한 최소 동전 개수
33+ 6. 초기화:
34+ - dp[0] = 0 (0원 만들기 = 동전 0개)
35+ - dp[1~amount] = 아직 계산 안 됨
36+
37+ dp = [float('inf')] * (amount + 1)
38+ dp[0] = 0
39+
40+ 7. 점화식:
41+ - 각 동전 coin에 대해
42+ - dp[x] = min(dp[x], dp[x - coin] + 1)
43+ - 의미: "x원 = (x-coin)원 + coin 1개"
44+
45+ 8. Eample) coins = [1, 2, 5], amount = 11
46+
47+ 초기: dp = [0, inf, inf, inf, ..., inf]
48+
49+ 동전 1 처리:
50+ dp[1] = min(inf, dp[0]+1) = 1
51+ dp[2] = min(inf, dp[1]+1) = 2
52+ dp[3] = min(inf, dp[2]+1) = 3
53+ ...
54+
55+ 동전 2 처리:
56+ dp[2] = min(2, dp[0]+1) = 1 # 2원 동전 1개!
57+ dp[3] = min(3, dp[1]+1) = 2 # 2+1
58+ dp[4] = min(4, dp[2]+1) = 2 # 2+2
59+ ...
60+
61+ 동전 5 처리:
62+ dp[5] = min(5, dp[0]+1) = 1 # 5원 동전 1개!
63+ dp[6] = min(6, dp[1]+1) = 2 # 5+1
64+ dp[10] = min(10, dp[5]+1) = 2 # 5+5
65+ dp[11] = min(11, dp[6]+1) = 3 # 5+5+1
66+
67+
68+ [최종 구현] Bottom-Up DP
69+ ────────────────────────────────────────────────────────────────────────────────
70+ 12. 모든 동전에 대해 반복
71+ 13. 각 동전으로 만들 수 있는 모든 금액 업데이트
72+ 14. 불가능하면 -1 반환 (dp[amount]가 여전히 무한대)
73+
74+ for coin in coins:
75+ for x in range(coin, amount + 1):
76+ dp[x] = min(dp[x], dp[x - coin] + 1)
77+
78+ return dp[amount] if dp[amount] != float('inf') else -1
79+
80+ 15. 시간복잡도: O(amount × coins) - 효율적!
81+ 16. 공간복잡도: O(amount) - dp 배열
82+ """
0 commit comments