参考链接
- https://leetcode-cn.com/problems/house-robber-iii/
题目描述
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
解题思路
跟之前的打家劫舍的区别在于,房屋的排列是一棵二叉树。列出状态转移方程即可求解:
r
o
o
t
的
最
大
金
额
=
{
root节点值+左子树的左右子树最大金额和+右子树的左右子树最大金额和 //如果不从当前房子中取钱
左子树的最大金额+右子树的最大金额 //如果从当前房子中取钱
root的最大金额=\begin{cases} & \text{root节点值+左子树的左右子树最大金额和+右子树的左右子树最大金额和 //如果不从当前房子中取钱} \\ & \text{左子树的最大金额+右子树的最大金额 //如果从当前房子中取钱} \end{cases}
root的最大金额={root节点值+左子树的左右子树最大金额和+右子树的左右子树最大金额和 //如果不从当前房子中取钱左子树的最大金额+右子树的最大金额 //如果从当前房子中取钱
代码
class Solution {
public:
unordered_map <TreeNode*, int> memo;
int rob(TreeNode* root) {
if (root == nullptr)
{
return 0;
}
if (memo.count(root) != 0)
{
return memo[root];
}
int do_it = root->val
+ (root->left == nullptr ? 0: rob(root->left->left) + rob(root->left->right))
+ (root->right == nullptr ? 0: rob(root->right->left) + rob(root->right->right));
int not_do = rob(root->left) + rob(root->right);
int res = max(do_it, not_do);
memo[root] = res;
return res;
}
};