目录
- 题目
- 思路
- 代码
题目
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root
。
除了 root
之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root
。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
示例 1:
输入: root = [3,2,3,null,3,null,1] 输出: 7 解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
示例 2:
输入: root = [3,4,5,1,3,null,1] 输出: 9 解释: 小偷一晚能够盗取的最高金额 4 + 5 = 9
提示:
- 树的节点数在
[1, 104]
范围内 0 <= Node.val <= 104
思路
读题目总结出
- 这是一个二叉树
- 二叉树每个节点,可以选择偷和不偷
- 当前节点选择偷的时候,父子节点都不能偷。
- 当前节点选择不偷的时候,父子节点可以选择偷或不偷
这是一题比较简单的树形DP,所以状态应该为Map<TreeNode, int[]> dp = new HashMap<>()
,每个节点int[]{偷, 不偷}
。
- 初始化
int[] n = int[]{node.val, 0}
- 当前节点选择偷钱时
n[0] = n[0] + dp.get(node.left)[1] + dp.get(node.right)[1]
- 当前节点选择不偷钱时,子节点可偷可不偷
n[1] = max(dp.get(node.left)[1], dp.get(node.left)[0]) + max(dp.get(node.right)[1], dp.get(node.right)[0])
代码
class Solution {
private void dfs(TreeNode node, Map<TreeNode, int[]> dp) {
if (node == null) return;
int[] n = new int[2];
n[0] = node.val;
dp.put(node, n);
dfs(node.left, dp);
dfs(node.right, dp);
if (node.left != null) {
int[] l = dp.get(node.left);
n[0] += l[1];
n[1] += Math.max(l[0], l[1]);
}
if (node.right != null) {
int[] r = dp.get(node.right);
n[0] += r[1];
n[1] += Math.max(r[0], r[1]);
}
}
// 0偷, 1不偷
public int rob(TreeNode root) {
Map<TreeNode, int[]> dp = new HashMap<>();
dfs(root, dp);
int[] r = dp.get(root);
return Math.max(r[0], r[1]);
}
}