The thief has found himself a new place for his thievery again. There is only one entrance to this area, called root.
Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that all houses in this place form a binary tree. It will automatically contact the police if two directly-linked houses were broken into on the same night.
Given the root of the binary tree, return the maximum amount of money the thief can rob without alerting the police.
Example 1:
3↙ ↘2 3↘ ↘3 1Input: root = [3,2,3,null,3,null,1]Output: 7Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
3↙ ↘4 5↙ ↘ ↘1 3 1Input: root = [3,4,5,1,3,null,1]Output: 9Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.
根据题目可知,可盗取最大值 f(root) = Math.max(root.val + f(root 的孙节点), f(root 的子节点))
,顺势使用递归解题:
/*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val = (val===undefined ? 0 : val)* this.left = (left===undefined ? null : left)* this.right = (right===undefined ? null : right)* }*//*** @param {TreeNode} root* @return {number}*/var rob = function(root) {if (!root) return 0return Math.max(root.val+ (root.left && root.left.left ? rob(root.left.left) : 0)+ (root.left && root.left.right ? rob(root.left.right) : 0)+ (root.right && root.right.left ? rob(root.right.left) : 0)+ (root.right && root.right.right ? rob(root.right.right) : 0),(root.left ? rob(root.left) : 0)+ (root.right ? rob(root.right) : 0))}
此时解题超时,接着进行优化。
/*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val = (val===undefined ? 0 : val)* this.left = (left===undefined ? null : left)* this.right = (right===undefined ? null : right)* }*//*** @param {TreeNode} root* @return {number}*/var rob = function(root) {const cache = new Map()return robRecursive(root, cache)}function robRecursive(node, cache) {if (!node) return 0if (cache.get(node)) return cache.get(node)const index = cache.index = cache.index + 1const curNodeMax = Math.max(node.val+ (node.left && node.left.left ? robRecursive(node.left.left, cache) : 0)+ (node.left && node.left.right ? robRecursive(node.left.right, cache) : 0)+ (node.right && node.right.left ? robRecursive(node.right.left, cache) : 0)+ (node.right && node.right.right ? robRecursive(node.right.right, cache) : 0),(node.left ? robRecursive(node.left, cache) : 0)+ (node.right ? robRecursive(node.right, cache) : 0))cache.set(node, curNodeMax)return curNodeMax}
技巧小结:使用 map 代替 object 来记录缓存,参考 http://muyunyun.cn/blog/c1nhctpd
前置知识点:在 Tree 数据结构中,使用后序遍历可以达到动态规划中至底向上遍历的效果。
当前节点可盗取最大值为 Max{f(node), g(node)}
,其中 f(node) 表示当前 node 节点被选中时的最大值,g(node) 表示当前节点非选中时的最大值。
/*** @param {TreeNode} root* @return {number}*/var rob = function(root) {const [selected, notSelected] = postRecursive(root)return Math.max(selected, notSelected)}function postRecursive(node) {if (!node) return [0, 0]const l = postRecursive(node.left)const r = postRecursive(node.right)const selected = node.val + l[1] + r[1]const notSelected = Math.max(l[0], l[1]) + Math.max(r[0], r[1])return [selected, notSelected]}