学习动态规划解决不同路径、最小路径和、打家劫舍、打家劫舍iii

学习动态规划|不同路径、最小路径和、打家劫舍、打家劫舍iii

62 不同路径

  • 动态规划,dp[i][j]表示从左上角到(i,j)的路径数量
  • dp[i][j] = dp[i-1][j] + dp[i][j-1]
java 复制代码
import java.util.Arrays;

/**
 * 路径数量
 * 动态规划,dp[i][j]表示从左上角到(i,j)的路径数量
 * dp[i][j] = dp[i-1][j] + dp[i][j-1]
 */
public class $62 {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];

        //边界
        for (int i = 0; i < m; i++) {
            dp[i][0] = 1;
        }
        for (int i = 0; i < n; i++) {
            dp[0][i] = 1;
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }

        return dp[m-1][n-1];
    }

    public int uniquePaths2(int m, int n) {
        int[] dp = new int[n];
        Arrays.fill(dp, 1);

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[j] += dp[j-1];
            }
        }
        return dp[n-1];
    }
}
java 复制代码
import java.util.Arrays;

/**
 * 路径数量
 * 动态规划,dp[i][j]表示从左上角到(i,j)的路径数量
 * dp[i][j] = dp[i-1][j] + dp[i][j-1]
 */
public class $62 {
    public int uniquePaths2(int m, int n) {
        int[] dp = new int[n];
        Arrays.fill(dp, 1);

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[j] += dp[j-1];
            }
        }
        return dp[n-1];
    }
}

64 最小路径和

  • 动态规划,dp[i][j]表示从左上角到(i,j)的最小路径和
  • grid[i][j] = Math.min(grid[i-1][j], grid[i][j-1]) + grid[i][j]
java 复制代码
/**
 * 最小路径和
 * grid[i][j] = Math.min(grid[i-1][j], grid[i][j-1]) + grid[i][j]
 */
public class $64 {
    public int minPathSum(int[][] grid) {
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (i==0 && j==0) continue;
                else if (i!=0 && j==0) grid[i][j] = grid[i-1][j] + grid[i][j];
                else if (i==0 && j!=0) grid[i][j] = grid[i][j-1] + grid[i][j];
                else grid[i][j] = Math.min(grid[i-1][j], grid[i][j-1]) + grid[i][j];
            }
        }
        return grid[grid.length-1][grid[0].length-1];
    }
}

198 打家劫舍

  • 动态规划,nums[i]表示前i间房屋能偷窃到的最高总金额
  • nums[i] = Math.max(nums[i-1], nums[i-2]+nums[i]);
java 复制代码
/**
 * 打家劫舍
 * 动态规划,nums[i]表示前i间房屋能偷窃到的最高总金额
 * nums[i] = Math.max(nums[i-1], nums[i-2]+nums[i]);
 */
public class $198 {
    public int rob(int[] nums) {
        //注意特殊值0,1
        if (nums == null || nums.length == 0) {
            return 0;
        }
        if (nums.length == 1) {
            return nums[0];
        }

        //nums[1]为nums[0]、nums[1]的最大值
        nums[1] = Math.max(nums[0], nums[1]);
        //从nums[2]开始
        for (int i = 2; i < nums.length; i++) {
            nums[i] = Math.max(nums[i-1], nums[i-2]+nums[i]);
        }
        return nums[nums.length-1];
    }
}

337 打家劫舍iii

  • 树形动态规划
  • 我们可以用 f(o)表示选择 o节点的情况下,o节点的子树上被选择的节点的最大权值和;
  • g(o)表示不选择 o节点的情况下,o节点的子树上被选择的节点的最大权值和;
  • l 和 r代表 o 的左右孩子。
  • 当 o 被选中时:o 的左右孩子都不能被选中,
复制代码
   故 o 被选中情况下子树上被选中点的最大权值和为 l和 r不被选中的最大权值和 + o的值
复制代码
   f(o)=g(l)+g(r)+o.val
  • 当 o不被选中时,o的左右孩子可以被选中,也可以不被选中。
复制代码
   对于 o的某个具体的孩子 x,它对 o 的贡献是 x被选中和不被选中情况下权值和的较大值。
复制代码
   g(o)=max{f(l),g(l)} + max{f(r),g(r)}
java 复制代码
import java.util.HashMap;
import java.util.Map;

/**
 * 打家劫舍iii
 * 树形动态规划
 * 我们可以用 f(o)表示选择 o节点的情况下,o节点的子树上被选择的节点的最大权值和;
 * g(o)表示不选择 o节点的情况下,o节点的子树上被选择的节点的最大权值和;
 * l 和 r代表 o 的左右孩子。
 *
 * 当 o 被选中时:o 的左右孩子都不能被选中,
 *      故 o 被选中情况下子树上被选中点的最大权值和为 l和 r不被选中的最大权值和 + o的值
 *      f(o)=g(l)+g(r)+o.val
 * 当 o不被选中时,o的左右孩子可以被选中,也可以不被选中。
 *      对于 o的某个具体的孩子 x,它对 o 的贡献是 x被选中和不被选中情况下权值和的较大值。
 *      g(o)=max{f(l),g(l)} + max{f(r),g(r)}
 */
public class $337 {
    Map<TreeNode, Integer> f = new HashMap<>();
    Map<TreeNode, Integer> g = new HashMap<>();

    public int rob(TreeNode root) {
        process(root);
        return Math.max(f.getOrDefault(root, 0), g.getOrDefault(root, 0));
    }

    private void process(TreeNode root) {
        if (root == null) {
            return;
        }

        process(root.left);
        process(root.right);

        f.put(root, root.val + g.getOrDefault(root.left, 0) + g.getOrDefault(root.right, 0));
        g.put(root, Math.max(f.getOrDefault(root.left, 0), g.getOrDefault(root.left, 0))
        + Math.max(f.getOrDefault(root.right, 0), g.getOrDefault(root.right, 0)));
    }

    //法一的简化版
    public int rob2(TreeNode root) {
        int[] rootStatus = process2(root);
        return Math.max(rootStatus[0], rootStatus[1]);
    }

    private int[] process2(TreeNode root) {
        if (root == null) {
            return new int[]{0, 0};
        }

        int[] l = process2(root.left);
        int[] r = process2(root.right);

        int selected = root.val + l[1] + r[1];
        int notSelected = Math.max(l[0], l[1]) + Math.max(r[0], r[1]);

        return new int[]{selected, notSelected};
    }
}
相关推荐
聚客AI5 小时前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v7 小时前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工9 小时前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农11 小时前
【React用到的一些算法】游标和栈
算法·react.js
博笙困了11 小时前
AcWing学习——双指针算法
c++·算法
moonlifesudo11 小时前
322:零钱兑换(三种方法)
算法
NAGNIP1 天前
大模型框架性能优化策略:延迟、吞吐量与成本权衡
算法
美团技术团队1 天前
LongCat-Flash:如何使用 SGLang 部署美团 Agentic 模型
人工智能·算法
Fanxt_Ja1 天前
【LeetCode】算法详解#15 ---环形链表II
数据结构·算法·leetcode·链表
侃侃_天下1 天前
最终的信号类
开发语言·c++·算法