{
  "slug": "coin-change",
  "title": "DP — Coin Change",
  "category": "Recursion & DP",
  "difficulty": "medium",
  "complexity": {
    "time": "O(amount × coins)",
    "space": "O(amount)"
  },
  "idea": "Solve every smaller amount first. For an amount, try each coin: using it costs one coin plus the best answer for the remainder. Because smaller amounts are already solved, each entry is one quick minimum.",
  "code": [
    "dp[0] = 0; everything else = ∞",
    "for amount in 1 .. target:",
    "    for each coin c <= amount:",
    "        dp[amount] = min(dp[amount], dp[amount-c] + 1)"
  ],
  "example": {
    "array": [
      1,
      3,
      4
    ],
    "target": 6
  },
  "invariant": "Each step is the real data structure at that step — the picture is a pure function of it.",
  "stepCount": 21,
  "steps": [
    {
      "i": 0,
      "op": "lanes",
      "caption": "Find the fewest coins making every amount up to 6.",
      "note": null,
      "codeLine": 1,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            0,
            0,
            0,
            0,
            0,
            0
          ],
          "focus": [
            null,
            null,
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            true,
            true,
            true,
            true,
            true,
            true,
            true
          ],
          "markers": [],
          "regions": []
        }
      ]
    },
    {
      "i": 1,
      "op": "lanes",
      "caption": "Amount 0 needs no coins at all.",
      "note": null,
      "codeLine": 1,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            0,
            0,
            0,
            0,
            0,
            0
          ],
          "focus": [
            "insert",
            null,
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            true,
            true,
            true,
            true,
            true,
            true
          ],
          "markers": [],
          "regions": []
        }
      ]
    },
    {
      "i": 2,
      "op": "lanes",
      "caption": "Use coin 1: dp[0] + 1 = 1 — best so far for 1.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            "compare",
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            0,
            0,
            0,
            0,
            0
          ],
          "focus": [
            "read",
            "write",
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            true,
            true,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 1,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 3,
      "op": "lanes",
      "caption": "Coin 3 is bigger than 1 — skip it.",
      "note": null,
      "codeLine": 3,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            "read",
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            0,
            0,
            0,
            0,
            0
          ],
          "focus": [
            null,
            null,
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            true,
            true,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 1,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 4,
      "op": "lanes",
      "caption": "Coin 4 is bigger than 1 — skip it.",
      "note": null,
      "codeLine": 3,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            "read"
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            0,
            0,
            0,
            0,
            0
          ],
          "focus": [
            null,
            null,
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            true,
            true,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 1,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 5,
      "op": "lanes",
      "caption": "Use coin 1: dp[1] + 1 = 2 — best so far for 2.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            "compare",
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            0,
            0,
            0,
            0
          ],
          "focus": [
            null,
            "read",
            "write",
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            true,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 2,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 6,
      "op": "lanes",
      "caption": "Coin 3 is bigger than 2 — skip it.",
      "note": null,
      "codeLine": 3,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            "read",
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            0,
            0,
            0,
            0
          ],
          "focus": [
            null,
            null,
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            true,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 2,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 7,
      "op": "lanes",
      "caption": "Coin 4 is bigger than 2 — skip it.",
      "note": null,
      "codeLine": 3,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            "read"
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            0,
            0,
            0,
            0
          ],
          "focus": [
            null,
            null,
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            true,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 2,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 8,
      "op": "lanes",
      "caption": "Use coin 1: dp[2] + 1 = 3 — best so far for 3.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            "compare",
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            3,
            0,
            0,
            0
          ],
          "focus": [
            null,
            null,
            "read",
            "write",
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 3,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 9,
      "op": "lanes",
      "caption": "Use coin 3: dp[0] + 1 = 1 — best so far for 3.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            "compare",
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            0,
            0,
            0
          ],
          "focus": [
            "read",
            null,
            null,
            "write",
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 3,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 10,
      "op": "lanes",
      "caption": "Coin 4 is bigger than 3 — skip it.",
      "note": null,
      "codeLine": 3,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            "read"
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            0,
            0,
            0
          ],
          "focus": [
            null,
            null,
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            true,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 3,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 11,
      "op": "lanes",
      "caption": "Use coin 1: dp[3] + 1 = 2 — best so far for 4.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            "compare",
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            2,
            0,
            0
          ],
          "focus": [
            null,
            null,
            null,
            "read",
            "write",
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            false,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 4,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 12,
      "op": "lanes",
      "caption": "Use coin 3: dp[1] + 1 = 2 — no better than 2.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            "compare",
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            2,
            0,
            0
          ],
          "focus": [
            null,
            "read",
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            false,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 4,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 13,
      "op": "lanes",
      "caption": "Use coin 4: dp[0] + 1 = 1 — best so far for 4.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            "compare"
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            0,
            0
          ],
          "focus": [
            "read",
            null,
            null,
            null,
            "write",
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            false,
            true,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 4,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 14,
      "op": "lanes",
      "caption": "Use coin 1: dp[4] + 1 = 2 — best so far for 5.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            "compare",
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            2,
            0
          ],
          "focus": [
            null,
            null,
            null,
            null,
            "read",
            "write",
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            false,
            false,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 5,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 15,
      "op": "lanes",
      "caption": "Use coin 3: dp[2] + 1 = 3 — no better than 2.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            "compare",
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            2,
            0
          ],
          "focus": [
            null,
            null,
            "read",
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            false,
            false,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 5,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 16,
      "op": "lanes",
      "caption": "Use coin 4: dp[1] + 1 = 2 — no better than 2.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            "compare"
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            2,
            0
          ],
          "focus": [
            null,
            "read",
            null,
            null,
            null,
            null,
            null
          ],
          "placeholders": [
            false,
            false,
            false,
            false,
            false,
            false,
            true
          ],
          "markers": [
            {
              "name": "a",
              "index": 5,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 17,
      "op": "lanes",
      "caption": "Use coin 1: dp[5] + 1 = 3 — best so far for 6.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            "compare",
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            2,
            3
          ],
          "focus": [
            null,
            null,
            null,
            null,
            null,
            "read",
            "write"
          ],
          "markers": [
            {
              "name": "a",
              "index": 6,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 18,
      "op": "lanes",
      "caption": "Use coin 3: dp[3] + 1 = 2 — best so far for 6.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            "compare",
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            2,
            2
          ],
          "focus": [
            null,
            null,
            null,
            "read",
            null,
            null,
            "write"
          ],
          "markers": [
            {
              "name": "a",
              "index": 6,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 19,
      "op": "lanes",
      "caption": "Use coin 4: dp[2] + 1 = 3 — no better than 2.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            "compare"
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            2,
            2
          ],
          "focus": [
            null,
            null,
            "read",
            null,
            null,
            null,
            null
          ],
          "markers": [
            {
              "name": "a",
              "index": 6,
              "tone": "bound"
            }
          ],
          "regions": []
        }
      ]
    },
    {
      "i": 20,
      "op": "lanes",
      "caption": "Amount 6 needs 2 coins.",
      "note": null,
      "codeLine": 4,
      "stats": null,
      "lanes": [
        {
          "id": "coins",
          "label": "coins available",
          "array": [
            1,
            3,
            4
          ],
          "focus": [
            null,
            null,
            null
          ],
          "markers": [],
          "regions": []
        },
        {
          "id": "dp",
          "label": "dp[a] = fewest coins for amount a",
          "array": [
            0,
            1,
            2,
            1,
            1,
            2,
            2
          ],
          "focus": [
            "settled",
            "settled",
            "settled",
            "settled",
            "settled",
            "settled",
            "settled"
          ],
          "markers": [],
          "regions": []
        }
      ]
    }
  ]
}