LeetCode 337. 打家劫舍 III DFS + 动态规划 详解

337. 打家劫舍 III

题目来源

337. 打家劫舍 III

题目分析

小偷发现了一个新的可行窃地区,这个地区排列成一棵二叉树。由于相邻的房屋同时被盗会触发报警,小偷需要在不触动报警的情况下,盗取能够盗取的最高金额。

题目难度

  • 难度:中等

题目标签

  • 标签:动态规划, 树, DFS

题目限制

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 400

解题思路

思路:DFS + 动态规划

  1. 定义问题

    • 每个节点有两个状态:被盗或者不被盗。
    • 如果当前节点被盗,那么它的子节点不能被盗。
    • 如果当前节点不被盗,那么它的子节点可以选择被盗或者不被盗。
  2. 状态转移

    • 利用 DFS 递归遍历整棵树,在每个节点处计算两种状态下的最大值。
  3. 递归公式

    • 对于每个节点 root,我们计算出两种情况的最大收益:
      • Select: 当前节点被盗的最大收益。
      • NotSelect: 当前节点不被盗的最大收益。
  4. 最终结果

    • 对根节点的两种状态取最大值,即为所求的最高金额。

核心算法步骤

  1. DFS 递归

    • 对每个节点进行 DFS 递归,计算左右子树的最大收益。
  2. 状态记录

    • 使用两个数组记录被盗和不被盗的最大收益。
  3. 返回最高金额

    • 根节点的两种状态中取最大值,即为最终的最高盗窃金额。

代码实现

以下是解决打家劫舍 III 问题的 Java 代码:

/**
 * 337. 打家劫舍 III
 * @param root 二叉树
 * @return 最高金额
 */
public int rob(TreeNode root) {
    int[] robbed = rob2(root);
    return Math.max(robbed[0], robbed[1]);
}

public int[] rob2(TreeNode root) {
    if (root == null) {
        return new int[]{0, 0};
    }
    int[] left = rob2(root.left);
    int[] right = rob2(root.right);
    // 如果不选择当前节点,则可以选择左右子节点的最大值
    int notSelect = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
    // 如果选择当前节点,则左右子节点不能选择
    int Select = root.val + left[0] + right[0];
    return new int[]{notSelect, Select};
}

代码解读

  • rob2(TreeNode root) 是一个递归函数,用于计算当前节点 root 两种状态下的最大收益。
  • notSelect 记录当前节点不被盗时的最大收益。
  • Select 记录当前节点被盗时的最大收益。
  • 最终返回一个数组,分别表示不被盗和被盗的两种情况。

性能分析

  • 时间复杂度O(N),其中 N 是树的节点数量。每个节点遍历一次。
  • 空间复杂度O(N),由于递归栈的空间开销。

测试用例

以下是一些测试用例,用于验证代码的正确性:

TreeNode<Integer> root1 = new TreeNode<>(3);
root1.left = new TreeNode<>(2);
root1.right = new TreeNode<>(3);
root1.left.right = new TreeNode<>(3);
root1.right.right = new TreeNode<>(1);
System.out.println(rob(root1)); // 输出: 7

TreeNode<Integer> root2 = new TreeNode<>(3);
root2.left = new TreeNode<>(4);
root2.right = new TreeNode<>(5);
root2.left.left = new TreeNode<>(1);
root2.left.right = new TreeNode<>(3);
root2.right.right = new TreeNode<>(1);
System.out.println(rob(root2)); // 输出: 9

效果

复杂度

总结

通过 DFS 和动态规划结合,我们能够有效地求解打家劫舍 III 问题。此方法思路清晰,效率较高,适用于大多数场景。


  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值