算法学习day38-动态规划

零钱兑换

核心思路

  • 就是完全背包的写法, 只是这个题是求最小值, 所以初始化的时候不能初始化0, 而是Integer.max_value

  • 以及赋值的时候, 如果dp[j - coin] = max, 就跳过, 说明这个硬币无法兑换=j

    java 复制代码
    public static int coinChange(int[] coins, int amount) {
        //dp[i] = 下标为i的时候 能填满的最少硬币数
        //推导
        //如果不放coins[i], dp[j]不变
        //如果放了coins[i], dp[j] = dp[j - coins[i]] + 1
        //初始化
        int[] dp = new int[amount + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int coin : coins) {
            for (int j = coin; j <= amount; j++) {
                if(dp[j - coin] == Integer.MAX_VALUE){
                    continue;
                }
                dp[j] = Math.min(dp[j], dp[j - coin] + 1);
            }
        }
        return dp[amount] == Integer.MAX_VALUE ? 0 : dp[amount];
    }

完全平方数

核心思路

  • 和零钱兑换思路几乎一致

  • dp定义: dp[j]代表的是 和为j的完全平方数的最小数量

  • 只是n即是物品, 也是背包容量

    java 复制代码
    public static int numSquares(int n) {
        int[] dp = new int[n + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int i = 1; i <= n; i++) {
            long sqrt = (long) Math.sqrt(i);
            //不是完全平方数就跳过
            if (sqrt * sqrt != (long) i) continue;
            for (int j = i; j <= n; j++) {
                if (dp[j - i] == Integer.MAX_VALUE) continue;
                dp[j] = Math.min(dp[j], dp[j - i] + 1);
            }
        }
        return dp[n];
    }
  • 算法优化后

    • 外层i直接平方, 这样就不用判断i是否是完全平方数, i * i 一定是从小到大的完全平方数, 1、4、9等
    java 复制代码
    int[] dp = new int[n + 1];
    Arrays.fill(dp, Integer.MAX_VALUE);
    dp[0] = 0;
    for (int i = 1; i * i <= n; i++) {
        for (int j = i * i; j <= n; j++) {
            if (dp[j - i * i] == Integer.MAX_VALUE) continue;
            dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
        }
    }
    return dp[n];

单词拆分

核心思路

  • 还是完全背包问题
  • 但是该题 不是求组合,而是排列
    • 因为单词是要求有序的,比如 leetcode,[code,leet], 就要先leet, 再code
例如
  • 输入: s = "catsanddog", wordDict = ["cat", "cats", "and", "sand", "dog"]

  • i = 3: j=0 匹配 "cat",dp[3] = T。

  • i = 4: j=0 匹配 "cats",dp[4] = T。

  • i = 7 ("catsand"):

  • 尝试 j = 3: dp[3] 是 T (cat),剩下 s[3:7] 是 "sand"。字典有 "sand",所以 dp[7] = T。

  • 尝试 j = 4: dp[4] 是 T (cats),剩下 s[4:7] 是 "and"。字典也有 "and",所以 dp[7] 再次被确认是 T。
    (只要有一个 j 能通,dp[7] 就是 true)

  • i = 10: j=7 匹配 "dog",且 dp[7] 是 T,所以 dp[10] = T。

  • 结果: 成功。

    java 复制代码
    public static boolean wordBreak(String s, List<String> wordDict) {
      boolean[] dp = new boolean[s.length() + 1];
      //dp的定义: 下标为i, 代表的是 从 0...i-1的单词能够被wordDict拼接而来
      dp[0] = true;
      for (int i = 1; i <= s.length(); i++) {
        for (int j = 0; j < i; j++) {
          dp[i] = dp[j] && wordDict.contains(s.substring(j, i));
          if (dp[i]) break;
        }
      }
      return dp[s.length()];
    }
相关推荐
wuweijianlove4 小时前
算法性能的渐近与非渐近行为对比的技术4
算法
_dindong4 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
AI成长日志4 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
黎阳之光4 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
skywalker_114 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
6Hzlia4 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
_李小白4 小时前
【OSG学习笔记】Day 38: TextureVisitor(纹理访问器)
android·笔记·学习
wfbcg5 小时前
每日算法练习:LeetCode 209. 长度最小的子数组 ✅
算法·leetcode·职场和发展
_日拱一卒5 小时前
LeetCode:除了自身以外数组的乘积
数据结构·算法·leetcode
计算机安禾5 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio