题目:
方法1:
题目分析:首先分析题目,大概就是记忆化递归也就是动态规划的题目,
1.对于每个节点来说都有两种选择要么偷要么就不偷,偷的话金额就可以加上当前的值,不偷的话就不能加上,这里我定义了一Boolean值,为true就表明当前节点可以偷,为false就表明当前节点不能偷
class Solution {
//记忆map
public Map<TreeNode,Integer> map=new HashMap<TreeNode, Integer>();
public int rob(TreeNode root) {
return dfs(root,true);
}
public int dfs(TreeNode node,boolean flag){
if(node==null){
return 0;
}
//返回从当前节点开始返回最大的偷钱选择 flag为真可以加上当前值 也可以不加 为false只能返回子节点的值
if(flag){
if(map.containsKey(node)){
return map.get(node);
}
//情况1:当前值+不偷左节点的值+不偷右节点的值
//情况2:左节点的最大值+右节点的最大值
int res1=node.val+ dfs(node.right,false)+dfs(node.left,false);
int res2=dfs(node.left,true)+dfs(node.right,true);
int res=Math.max(res1,res2);
//这里map存的是这个节点的最大值无论偷还是不偷
map.put(node,res);
return res;
}
else {
//只能返回子节点的值
return dfs(node.left,true)+dfs(node.right,true);
}
}
}
方法2:
官方的写的实在是简洁阿
class Solution {
//f为不偷的map t为偷的map
Map<TreeNode, Integer> f = new HashMap<TreeNode, Integer>();
Map<TreeNode, Integer> t = new HashMap<TreeNode, Integer>();
public int rob(TreeNode root) {
dfs(root);
return Math.max(f.getOrDefault(root, 0), t.getOrDefault(root, 0));
}
public void dfs(TreeNode node){
if(node ==null){
return;
}
dfs(node.left);
dfs(node.right);
//偷当前节点+不偷左节点的值+不偷右节点的值
t.put(node, node.val + f.getOrDefault(node.left, 0) + f.getOrDefault(node.right, 0));
//不偷当前节点+ Max(偷左节点和不偷左节点)+ Max(偷右节点和不偷右节点)
f.put(node, Math.max(f.getOrDefault(node.left, 0), t.getOrDefault(node.left, 0)) + Math.max(f.getOrDefault(node.right, 0), t.getOrDefault(node.right, 0)));
}
}