[LintCode 535.] 打劫房屋 III
LintCode 535. 打劫房屋 III
题目描述
在上次打劫完一条街道之后和一圈房屋之后,窃贼又发现了一个新的可以打劫的地方,但这次所有的房子组成的区域比较奇怪,聪明的窃贼考察地形之后,发现这次的地形是一颗二叉树。与前两次偷窃相似的是每个房子都存放着特定金额的钱。你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且当相邻的两个房子同一天被打劫时,该系统会自动报警。
算一算,如果今晚去打劫,你最多可以得到多少钱,当然在不触动报警装置的情况下。
样例
样例1
输入: {3,2,3,#,3,#,1}
输出: 7
解释:
最多能偷 3 + 3 + 1 = 7.
3
/ \
2 3
\ \
3 1
样例2
输入: {3,4,5,1,3,#,1}
输出: 9
解释:
最多能偷 4 + 5 = 9.
3
/ \
4 5
/ \ \
1 3 1
解题思路
这题是House Robber和House Robber II的扩展,只不过这次地形由直线和圈变成了二叉树。
解题思路与 [LintCode 614.] 二叉树的最长连续子序列 II 类似:
使用记录每一个结点的状态,递归计算得出答案。
这里对于每一个结点都有两状态,被抢劫,或者不被抢劫。需要的状态为当前子树上抢劫的最大收益,对于一个结点:
- 如果被抢劫,那么收益就是当前结点的收益 + 两棵子树上不抢劫各自根结点的收益;
- 如果不抢劫,那么收益就是两棵子树上的最大收益之和 —— 每棵子树都可以抢根节点或者不抢根节点,取收益最大的操作即可。
最终我们需要的就是从根节点的两种操作中的收益中,取最大收益即可。
补充测试样例
{1, 2, 3, 5, 4}
1
/ \
2 3
/ \
5 4
最多能偷 5 + 4 + 3 = 12。
参考代码
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
struct Res {
int rob;
int skip;
};
class Solution {
public:
/**
* @param root: The root of binary tree.
* @return: The maximum amount of money you can rob tonight
*/
int houseRobber3(TreeNode * root) {
// write your code here
Res res = rob3(root);
return max(res.rob, res.skip);
}
static Res rob3(TreeNode* r) {
if (r == NULL) return {0, 0};
Res res1 = rob3(r->left);
Res res2 = rob3(r->right);
int rob = r->val + res1.skip + res2.skip;
int skip = max(res1.rob, res1.skip) + max(res2.rob, res2.skip);
return {rob, skip};
}
};