采用记忆化搜索方法,将问题转化为完全背包模型,即使用无限数量的物品来凑出目标金额amount。
边界条件处理:
- 当物品下标为负数时,表示没有可用物品
- 若当前金额恰好为0,说明成功凑出目标金额
- 否则视为无效方案,返回INT_MAX表示不合法
非边界条件处理:
- 当前物品面值大于剩余金额时: 直接继承前i-1个物品凑出金额c的最小硬币数
- 否则: 比较两种情况,取最小值:
- 使用当前物品:前i-1个物品凑出(c - coins[i])的最小硬币数加1
- 不使用当前物品:前i-1个物品凑出c的最小硬币数
-
class Solution { public: int coinChange(vector<int>& coins, int amount) { int n = coins.size(); vector<vector<int>> cache(n,vector<int>(amount + 1,-1)); auto dfs = [&] (this auto && dfs,int i,int c)->int { if (i < 0) { return c == 0 ? 0 : INT_MAX / 2; } if (cache[i][c] != -1) { return cache[i][c]; } if (c < coins[i]) { return cache[i][c] = dfs(i - 1,c); } return cache[i][c] = min (dfs(i - 1,c) , dfs(i,c - coins[i]) + 1); }; int ans = dfs(n - 1,amount); return ans == INT_MAX / 2 ? -1:ans; } };
时间复杂度:O(n*amount)
空间复杂度:O(n*amount)