每天一道题-1

322零钱兑换

在这个题目中,开始思考的方法就是从特殊到普适的过程。

  1. 暴力求法,直接每一层进行一次对不同面额的硬币进行一次遍历减少,amount - coin for coins 剩余的总数再进行如何进行遍历处理。直到amount = 0得到结果后再比较所需的货币数量

  2. 由暴力解法,可以更好的想到 BFS 广度优搜索 + 记忆化 也就是看那个分支更快的到达终点。

    class Solution {
        public int coinChange(int[] coins, int amount) {
            if (amount < 1) {
                return 0;
            }
            return bfs(coins, rem, new int[amount]);
        }
        private int bfs(int[] coins, int rem, int[] count) {
            // 结束标志
            if (rem < 0) {
                return -1;
            }
            if (rem == 0) {
                return 0;
            }
            // 检测存放结果的地方是否得到结果
            if (count[rem - 1] != 0) {
                return count[rem - 1];
            }
            int min = Integer.MAX_VALUE;
            for (int coin : coins) {
                // 遍历一个状态下减去所有硬币的可能
                int res = bfs(coins, rem - coin, count);
                // 筛选掉无法兑换成功的可能
                if (res >= 0 && res < min) {
                    min = 1 + res;
                }
            }
            // 存放每个状态的最优值
            count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
            return count[rem - 1];
        }
    }
    
  3. 总结下这个问题,其实是一个优化问题,可以使用 DP 动态规划 的解决方法

    class Solution {
        public int coinChange(int[] coins, int amount) {
            int max = amount + 1; //作为一个标志位,在最后与amount进行比较判断是否可以兑换成功
            int[] dp = new int[max];
            Arrays.fill(dp, max);
            dp[0] = 0;
            for (int i = 1; i < amount; i ++) {
                for (int j = 0; j < coins.length; j ++) {
                    // 判断是否有硬币小于当前总数
                    if (coins[j] <= i) {
                        // 多次比较,得到当前总数的最优解
                        dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                    }
                }
            }
            // 通过预先放置的值来进行比较,从而得知是否兑换成功
            return dp[amount] > amount ? -1 : dp[amount];
        }
    }
    
posted @ 2021-08-13 15:08  做个认真生活的人  阅读(32)  评论(0)    收藏  举报