{"componentChunkName":"component---src-templates-blog-post-js","path":"/algorithm/최소-동전수-dp-coin-change/","result":{"data":{"site":{"siteMetadata":{"title":"Bottlehs Tech Blog","description":"웹·앱·AI 개발자 전병훈(bottlehs)의 기술 블로그. AI·LLM, JavaScript·Vue, Spring Boot, 알고리즘, 블록체인 실무 가이드를 다룹니다","siteUrl":"https://www.bottlehs.dev","author":{"name":"Jeon Byung Hun","summary":"개발을 즐기는 bottlehs - Engineer, MS, AI, FE, BE, OS, IOT, Blockchain, 설계, 테스트"},"social":{"github":"bottlehs","codepen":"bottlehs"}}},"markdownRemark":{"id":"3ef2a479-4f5b-54ec-8f33-199c7b655221","excerpt":"최소 동전 수 (Coin Change, DP) 그리디로는 항상 최적을 보장하지 못하는 거스름돈 문제를, 동적 계획법으로 최적해로 해결한다. 정의 여러 종류의 동전으로 딱 맞게 금액 N…","html":"<p><img src=\"/assets/algorithm.png\" alt=\"최소 동전 수 (Coin Change, DP)\" title=\"최소 동전 수 (Coin Change, DP)\"></p>\n<p>그리디로는 항상 최적을 보장하지 못하는 거스름돈 문제를, 동적 계획법으로 최적해로 해결한다.</p>\n<h2 id=\"정의\" style=\"position:relative;\"><a href=\"#%EC%A0%95%EC%9D%98\" aria-label=\"정의 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>정의</h2>\n<p>여러 종류의 동전으로 딱 맞게 금액 N을 만들 때 필요한 동전 개수의 최소값을 구하는 문제다. 핵심은 “동전의 조합”을 고려한다는 점인데, 같은 금액이라도 어떤 동전을 어떻게 조합하느냐에 따라 필요한 개수가 달라질 수 있다. 예를 들어 정규 화폐 체계(10,000/5,000/1,000/500/100/50/10)에서는 보통 큰 단위부터 쓰는 그리디가 잘 통하지만, 10·7·5·1처럼 구성된 세트에서는 14를 만들 때 10+1+1+1+1(5개)보다 7+7(2개)이 더 낫다.</p>\n<p>동적 계획법(DP)은 이런 경우에 최적해를 보장한다. 작은 금액부터 차례로 “해답을 저장”해 가면서, 더 큰 금액의 답을 이전 결과를 이용해 빠르게 계산할 수 있게 한다. 만들 수 있는 경우에는 최소 동전 개수를, 어떤 조합으로도 만들 수 없는 금액이라면 -1을 반환해 “불가능”을 명확히 표현한다.</p>\n<h2 id=\"구현\" style=\"position:relative;\"><a href=\"#%EA%B5%AC%ED%98%84\" aria-label=\"구현 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>구현</h2>\n<p>DP 배열 <code class=\"language-text\">dp[x]</code>를 “금액 x를 만드는 최소 동전 개수”로 정의하고, 기저값으로 <code class=\"language-text\">dp[0]=0</code>을 둔다. 이후 1부터 N까지 올라가며 모든 동전에 대해 <code class=\"language-text\">x-coin</code>이 유효하면 <code class=\"language-text\">dp[x] = min(dp[x], dp[x-coin] + 1)</code>로 갱신한다. 이렇게 하면 동전 하나를 추가해 x를 만드는 가장 좋은 방법을, 이미 구해 둔 작은 금액의 해답을 기반으로 빠르게 결정할 수 있다.</p>\n<p>초깃값은 큰 수(INF)로 채워 “아직 방법을 모름”을 표현하고, 마지막에 <code class=\"language-text\">dp[N]</code>이 여전히 INF라면 만들 수 없는 금액이므로 -1을 반환한다. 구현 시 입력 유효성(음수나 정수가 아닌 값), 동전 배열이 비었을 때의 처리, 그리고 동전 순서에 의존하지 않도록 모든 동전을 균등히 순회하는 방식을 지키면 견고한 풀이가 된다.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">minCoins</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">amount<span class=\"token punctuation\">,</span> coins</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>Number<span class=\"token punctuation\">.</span><span class=\"token function\">isInteger</span><span class=\"token punctuation\">(</span>amount<span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> amount <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span>\n  <span class=\"token keyword\">const</span> <span class=\"token constant\">INF</span> <span class=\"token operator\">=</span> amount <span class=\"token operator\">+</span> <span class=\"token number\">1</span>\n  <span class=\"token keyword\">const</span> dp <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Array</span><span class=\"token punctuation\">(</span>amount <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token constant\">INF</span><span class=\"token punctuation\">)</span>\n  dp<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span>\n\n  <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> x <span class=\"token operator\">&lt;=</span> amount<span class=\"token punctuation\">;</span> x<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> coin <span class=\"token keyword\">of</span> coins<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">-</span> coin <span class=\"token operator\">>=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        dp<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">min</span><span class=\"token punctuation\">(</span>dp<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> dp<span class=\"token punctuation\">[</span>x <span class=\"token operator\">-</span> coin<span class=\"token punctuation\">]</span> <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> dp<span class=\"token punctuation\">[</span>amount<span class=\"token punctuation\">]</span> <span class=\"token operator\">===</span> <span class=\"token constant\">INF</span> <span class=\"token operator\">?</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span> <span class=\"token operator\">:</span> dp<span class=\"token punctuation\">[</span>amount<span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// 예시 실행</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">minCoins</span><span class=\"token punctuation\">(</span><span class=\"token number\">14</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 2 (7+7)</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">minCoins</span><span class=\"token punctuation\">(</span><span class=\"token number\">51860</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">10000</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5000</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">,</span> <span class=\"token number\">500</span><span class=\"token punctuation\">,</span> <span class=\"token number\">100</span><span class=\"token punctuation\">,</span> <span class=\"token number\">50</span><span class=\"token punctuation\">,</span> <span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h2 id=\"데모\" style=\"position:relative;\"><a href=\"#%EB%8D%B0%EB%AA%A8\" aria-label=\"데모 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>데모</h2>\n<p><a href=\"https://codepen.io/pen/?template=yLgbWPj\">https://codepen.io/pen/?template=yLgbWPj</a></p>","tableOfContents":"<ul>\n<li><a href=\"/algorithm/%EC%B5%9C%EC%86%8C-%EB%8F%99%EC%A0%84%EC%88%98-dp-coin-change/#%EC%A0%95%EC%9D%98\">정의</a></li>\n<li><a href=\"/algorithm/%EC%B5%9C%EC%86%8C-%EB%8F%99%EC%A0%84%EC%88%98-dp-coin-change/#%EA%B5%AC%ED%98%84\">구현</a></li>\n<li><a href=\"/algorithm/%EC%B5%9C%EC%86%8C-%EB%8F%99%EC%A0%84%EC%88%98-dp-coin-change/#%EB%8D%B0%EB%AA%A8\">데모</a></li>\n</ul>","wordCount":{"words":238},"fields":{"slug":"/algorithm/최소-동전수-dp-coin-change/","image":"/assets/algorithm.png","faq":[]},"frontmatter":{"title":"최소 동전 수 (Coin Change, DP)","date":"2025년 10월 30일","dateISO":"2025-10-30T00:00:00.000Z","updatedISO":null,"category":"algorithm","description":"동적 계획법(DP)을 사용하여 특정 금액을 만들기 위한 최소 동전 개수를 구한다. 그리디가 항상 최적을 보장하지 않는 경우에도 최적해를 보장하는 방법이다.","tags":["동적 계획법","Dynamic Programming","Coin Change","알고리즘","Algorithm","JavaScript"]}}},"pageContext":{"slug":"/algorithm/최소-동전수-dp-coin-change/","previous":{"fields":{"slug":"/ai/Function-Calling과-Tool-Use-LLM이-실제-도구를-사용하는-방법/"},"frontmatter":{"title":"Function Calling과 Tool Use - LLM이 실제 도구를 사용하는 방법","tags":["Function Calling","Tool Use","LLM","API","OpenAI","Anthropic","Google","AI","Agent"]}},"next":{"fields":{"slug":"/algorithm/너비우선탐색-breadth-first-search/"},"frontmatter":{"title":"너비 우선 탐색 (Breadth-First Search, BFS)","tags":["너비 우선 탐색","Breadth-First Search","BFS","알고리즘","Algorithm","JavaScript"]}}}},"staticQueryHashes":["213619243","3262363727"]}