LeetCode 322题 零钱兑换

123 阅读1分钟

题目链接

这是一个求最值的问题,可以用动态规划来解。

我们以

coins = [1, 2, 5], amount = 11

为例从后往前思考:

image.png

要寻求11的最少次数就需要先找到10,9,6的最少次数然后+1求最小值即可。 而找10的最少次数需要找9,8,5的最少次数然后+1求最小值即可。...以此类推。

图中红色部分表明了计算过程中有重复计算的问题。需要避免掉,防止算法超时。

function coinChange(coins: number[], amount: number): number {
    const cache: number[] = []; // 缓存已经算过的结果

    const _coinChange = (coins: number[], amount: number) => {
        if (amount === 0) {
            return 0;
        }

        if (coins.includes(amount)) {
            return 1;
        }

        if (cache[amount]) {
            return cache[amount];
        }

        const arr = coins.map((item) => {
            if (item > amount) {
                // 凑不出来
                return -1;
            }
            const change =  _coinChange(coins, amount - item);
            if(change === -1) {
                return change;
            }
            // 可以凑出就把结果+1
            return change + 1;
        });

        // 去掉-1
        const changeArr = arr.filter(item => item !== -1);

        // 我们只要最少次数
        const minTime = changeArr.length ? Math.min.apply(Math, changeArr) : -1;

        // 加缓存
        cache[amount] = minTime;
        return minTime;
    }
    return _coinChange(coins, amount);
};