当前位置: 首页 > news >正文

动态规划(2)

LCR 103. 零钱兑换

零钱找零

1.暴力

思路

大问题拆解子问题

边界条件: amount刚好等于0 说明方法起效(极限)

                amount小于0 说明价格不能再减

1 + dp(coins, n - coin) 表示每次可以取的次数

class Solution {public int coinChange(int[] coins, int amount) {return dp(coins, amount);}public int dp(int[] coins,int amount){if (amount == 0) return 0;if (amount < 0) return -1;int res = Integer.MAX_VALUE;for(int coin : coins){int subproblem = dp(coins, amount - coin);if (subproblem == -1) continue;res =  Math.min(res, subproblem + 1);}return res == Integer.MAX_VALUE ? -1 : res;}public static void main(String[] args) {int[] coins = {1,2,5};int amount = 11;Solution s = new Solution();System.out.println(s.coinChange(coins, amount));}
}

超时

2.剪枝

因为每个的amount都被重复计算

设置memo 如果memo被计算过直接返回

import java.util.Arrays;class Solution {int[] memo;public int coinChange(int[] coins, int amount) {memo  = new int[amount + 1];/*     for (int i = 0; i < amount + 1; i++) {memo[i] = -3;}*/Arrays.fill(memo,-3);return dp(coins, amount);}public int dp(int[] coins,int amount){if (amount == 0) return 0;if (amount < 0) return -1;int res = Integer.MAX_VALUE;if (memo[amount] != -3) return memo[amount];for(int coin : coins){int subproblem = dp(coins, amount - coin);if (subproblem == -1) continue;res =  Math.min(res, subproblem + 1);}return  memo[amount] = res == Integer.MAX_VALUE ? -1 : res;//   return res == Integer.MAX_VALUE ? -1 : res;}public static void main(String[] args) {int[] coins = {1,2,5};int amount = 11;Solution s = new Solution();System.out.println(s.coinChange(coins, amount));}
}

3.灵神算法

不一样的思路cache对应dfs

如果当前的节点费用小于当前coin 则返回上一个节点的相同费用

如果C小于0 则返回-1 说明不存在刚好的策略

而对每一个选项都有选和不选的两种选择

class Solution {private int[] coins;private int[][] cache;public int coinChange(int[] coins, int amount) {this.coins = coins;int n = coins.length;cache = new int[n][amount + 1];for (int i = 0; i < n; i++)Arrays.fill(cache[i], -1); // -1 表示没用访问过int ans = dfs(n - 1, amount);return ans < Integer.MAX_VALUE / 2 ? ans : -1;}private int dfs(int i, int c) {if (i < 0) return c == 0 ? 0 : Integer.MAX_VALUE / 2; // 除 2 是防止下面 + 1 溢出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] = Math.min(dfs(i - 1, c), dfs(i, c - coins[i]) + 1);}
}作者:灵茶山艾府
链接:https://leetcode.cn/problems/gaM7Ch/solutions/2128055/jiao-ni-yi-bu-bu-si-kao-dong-tai-gui-hua-kmrs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

核心思路

  1. 状态定义

    • cache[i][c] 表示使用前 i 种硬币组成金额 c 的最少硬币数量
    • 如果 cache[i][c] = -1,表示该状态还未被计算过
  2. 状态转移

    • 对于每种硬币 coins[i],有两种选择:
      1. 不使用当前硬币 coins[i],则状态转移为 dfs(i-1, c)
      2. 使用至少一枚当前硬币 coins[i],则状态转移为 dfs(i, c-coins[i]) + 1
    • 取两种选择中的较小值作为结果
  3. 初始条件

    • 当 i < 0(没有硬币可用)时:
      • 如果 c == 0,返回 0(不需要任何硬币)
      • 否则返回 Integer.MAX_VALUE / 2(表示无法组成该金额)
      • 除以 2 是为了防止后续计算中 +1 导致整数溢出
  4. 结果处理

    • 如果最终结果小于 Integer.MAX_VALUE / 2,说明存在解,返回该结果
    • 否则返回 -1 表示无法组成目标金额

关键细节解释

  1. Integer.MAX_VALUE/ 2 的作用

    • 在动态规划中,通常用无穷大表示不可达状态
    • 这里使用 Integer.MAX_VALUE / 2 而不是 Integer.MAX_VALUE 是为了避免在状态转移时发生整数溢出
    • 例如,如果 dfs(i-1, c) 或 dfs(i, c-coins[i]) 返回 Integer.MAX_VALUE,直接加 1 会导致溢出
  2. 二维数组的优势

    • 相比一维数组解法,二维数组可以更清晰地表达状态转移过程
    • 可以更方便地处理 “每种硬币无限使用” 的条件(通过 dfs(i, c-coins[i]) 实现)
  3. 记忆化的作用

    • 通过 cache 数组记录已计算的状态,避免重复计算
    • 时间复杂度从指数级降低到 O (n * amount),其中 n 是硬币种类

4.压缩dp数组()

动态规划解题套路框架 | labuladong 的算法笔记

class Solution {public int coinChange(int[] coins, int amount) {int[] dp = new int[amount + 1];// 数组大小为 amount + 1,初始值也为 amount + 1Arrays.fill(dp, amount + 1);// base casedp[0] = 0;// 外层 for 循环在遍历所有状态的所有取值for (int i = 0; i < dp.length; i++) {// 内层 for 循环在求所有选择的最小值for (int coin : coins) {// 子问题无解,跳过if (i - coin < 0) {continue;}dp[i] = Math.min(dp[i], 1 + dp[i - coin]);}}return (dp[amount] == amount + 1) ? -1 : dp[amount];}
}

相关文章:

  • 7. Ext系列文件系统
  • 深度学习介绍
  • 如何选择最高效的沟通方式?
  • 光耦电路学习,光耦输入并联电阻、并联电容,光耦输出滤波电路
  • 国产高云FPGA实现视频采集转UDP以太网输出,FPGA网络摄像头方案,提供2套Gowin工程源码和技术支持
  • 2023年12月四级真题Reading Comprehension的分析总结
  • SpringCloud 分布式锁Redisson锁的重入性 高并发 获取锁
  • 【氮化镓】钝化层对p-GaN HEMT阈值电压的影响
  • Qt 事件传递的完整流程
  • 板凳-------Mysql cookbook学习 (九--3)
  • AXURE-动态面板
  • 软考 系统架构设计师系列知识点之杂项集萃(79)
  • h5的aliplayer-min.js 加密视频会走到debugger
  • 晶台光耦在手机PD快充上的应用
  • [游戏设计原理_1] 对称性和同步性 | 合作与对抗 | 公平 | 反馈循环
  • 电工基础【4】点动接线实操
  • 火语言RPA--建立界面应用
  • STM32外部中断(EXTI)以及旋转编码器的简介
  • 第三十三天打卡复习
  • Java 中 i++ 与 ++i 的区别及常见误区解析
  • 莱州网站建设关键字排名优化网络托管微信代运营/市场seo是什么意思
  • 怎么在建设部网站查注册造价师/腾讯云域名购买
  • wordpress lensnews/关键词的优化方法
  • 利用海康威视做直播网站/指数基金
  • 建设网站只/免费网络推广软件
  • 免费制作网站net域名/天津百度优化