我们在前两集(第一集,第二集)中通过使用动态规划顺利的通过了挑战,享受了零元大抢购和无限量自助。现在我们要挑战最高难度的富豪区。富豪区的安保果然不同凡响,采用的二叉树的结构,当年Homebrew的作者Max Howell挑战Google就是被二叉树打败。那鸡汤文不是常说XX之下没有一片雪花是无辜的,富豪区居民作为底层制度的设计者需要为整个事件负责。打劫只是手段,目标是要建立一个更公平的制度。
https://www.lintcode.com/problem/house-robber-iii/
遇到二叉树,凭本能就意识到这个问题应该使用递归。问题的本质和之前还是一样,这个节点是抢还是不抢。所以我们每次递归返回的是当前节点作为根节点能获得的最大收益:1)包含该节点;2)不包含该节点。
实现代码如下:
# Python
class Solution:
# @param {TreeNode} root, the root of binary tree.
# @return {int} The maximum amount of money you can rob tonight
def houseRobber3(self, root):
# write your code here
return max(self._houseRobber3(root))
def _houseRobber3(self, root):
if not root:
return (0, 0)
rob_left = self._houseRobber3(root.left)
rob_right = self._houseRobber3(root.right)
not_rob = rob_left[1] + rob_right[1] + root.val
rob = max(rob_left) + max(rob_right)
return (not_rob, rob)
// Java
public class Solution {
/**
* @param root: The root of binary tree.
* @return: The maximum amount of money you can rob tonight
*/
public int houseRobber3(TreeNode root) {
// write your code here
// 递归,但是每次要返回两个结果,一个包含该节点的,一个不包含该节点的。
int[] ret = _houseRobber3(root);
return Math.max(ret[0], ret[1]); // [包含,不包含]
}
protected int[] _houseRobber3(TreeNode node) {
int[] ret = new int[]{0, 0};
if (node != null) {
int[] rl = _houseRobber3(node.left);
int[] rr = _houseRobber3(node.right);
ret[0] = rl[1] + rr[1] + node.val;
ret[1] = Math.max(rl[0], rl[1]) + Math.max(rr[0], rr[1]);
}
return ret;
}
}
OK,愉快的在富豪区均贫富,三部曲顺利收工。