---
# System prepended metadata

title: 322. Coin Change
tags: [JavaScript, Leetcode]

---

# 322. Coin Change

### Idea

因為目的是找到**符合條件之總和所需的最小金幣數量**<br/>
故決定用動態規劃來嘗試解決此問題

解題之前 先定義動態規劃的狀態和觀察狀態間的關聯性:

1. **dp[sum] 代表金幣加總為 sum 時所需要的最小金幣數**
2. 目標總和 amount 以下之可能發生的子總和 sum 完全是取決於**金幣的種類**而定

經過以上思考後寫出第一個跑得過的解<br/>
時間複雜度為 O( amount 大小 \* coins 長度)<br/>
空間複雜度為 O( amount 大小)

```javascript
function coinChange(coins, amount) {
  const dp = Array(amount + 1).fill(Infinity)
  dp[0] = 0
  for (let sum = 0; sum <= amount; sum++) {
    for (let coin of coins) {
      if (sum - coin >= 0) dp[sum] = Math.min(dp[sum], dp[sum - coin] + 1)
    }
  }
  return dp[amount] === Infinity ? -1 : dp[amount]
}
```

### Refactor

後來思考了一下為何效能不佳<br/>
**最外層迴圈真的有必要從 0 → amount 嗎?**<br/>
**其實只以某個基準 coin 的值 → amount 也是完全 ok 的吧**<br/>
因此把迴圈的條件內外對調微調了一下<br/>
省下了不少無意義的回圈

```javascript
function coinChange(coins, amount) {
  const dp = Array(amount + 1).fill(Infinity)
  dp[0] = 0
  for (let coin of coins) {
    for (let sum = coin; sum <= amount; sum++) {
      dp[sum] = Math.min(dp[sum], dp[sum - coin] + 1)
    }
  }
  return dp[amount] === Infinity ? -1 : dp[amount]
}
```

###### tags: `Leetcode` `JavaScript`
