零钱兑换

题目链接

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

示例:

输入:coins = [1, 2, 5], amount = 11
输出:3 
解释:11 = 5 + 5 + 1

思路

解法一:

本题与279.完全平方数解题方法一致,都是求最小问题,很容易想到 BFS

20220122111320-2022-01-22-11-13-21

  1. amount 看作根节点,构造多叉树,其节点为平方数;
  2. 每次从大到小进行取值,若差值为 0,则证明找到最短路径;
  3. 使用 set 消除同一层中相等的数重复计算情况。

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        if (amount == 0) return 0;
        unordered_set<int> visited;  //记录访问过的节点值
        queue<int> q;
        int step = 0;
        q.push(amount);
        while (q.size()) {
            int len = q.size();
            step++;
            while (len--) {
                int j = q.front();
                q.pop();
                for (int coin : coins) { // 遍历硬币
                    int m = j - coin;
                    if (m == 0) { // 如果凑齐,直接返回
                        return step;
                    }
                    if (m < 0 ) {
                        continue;
                    }
                    if (!visited.count(m)) { // 若没有记录过该值,加入队列,消除同一层中相同的数
                        visited.insert(m);
                        q.push(m);
                    }
                }
            }
        }
    return -1;
        
    }
};

参考链接