思路
树形DP
说起来逻辑还是很好理解的
dp的长度只有2 !含义就是 这个节点 [偷,不偷]的最大金额
然后递归做
当前节点不偷,那么金钱=左子点[偷,不偷]最大值 + 右子点[偷,不偷]最大值
当前节点偷,那么金钱 =当前节点钱+左右子点都不偷
DP来做,看代码
var rob = function(root) {const robOrder =function(node){// 递归出口if (!node) return [0, 0];const left =robOrder(node.left)const right =robOrder(node.right)// 不偷当前节点,左右子节点都可以偷或不偷,取最大值const Donot =Math.max(left[0],left[1])+Math.max(right[1],right[0])// 偷当前节点,左右子节点只能不偷const Do =node.val +left[0] +right[0]// [不偷,偷]return [Donot, Do]};const res =robOrder(root)console.log(res)return Math.max(...res)};
最基本的递归法
var rob = function (root) {
if (root == null) return 0;
let val1 = root.val; //偷当前节点 并且偷其左右孙子
if (root.left) val1 += rob(root.left.left) + rob(root.left.right);
if (root.right) val1 += rob(root.right.left) + rob(root.right.right);
let val2 = rob(root.left) + rob(root.right); // 不偷当前节点 偷其左右孩子
return Math.max(val1, val2);
};
记忆化递归
let rob = root => {
let map = new Map();
let inner = (root) => {
if (!root) return 0;
if (map.has(root)) return map.get(root); // 记忆化,之前存在过 直接返回无须进行重复计算
let val1 = root.val; //偷当前节点 并且偷其左右孙子
if (root.left) val1 += inner(root.left.left) + inner(root.left.right);
if (root.right) val1 += inner(root.right.left) + inner(root.right.right);
let val2 = inner(root.left) + inner(root.right); // 不偷当前节点 偷其左右孩子
let res = Math.max(val1, val2);
map.set(root, res);
return res;
}
return inner(root);
}
