LeetCode 打家劫舍 III
小偷发现了一个新的窃点,该地区只有一个入口,记为 root。除了 root 之外,每栋房子有且只有一个'父'房子与之相连。侦察后发现,所有房屋的排列类似于一棵二叉树。如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
给定二叉树的 root,返回在不触动警报的情况下,小偷能够盗取的最高金额。
示例 1

输入:root = [3,2,3,null,3,null,1]
输出:7
解释:小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
示例 2

输入:root = [3,4,5,1,3,null,1]
输出:9
解释:小偷一晚能够盗取的最高金额 4 + 5 = 9
提示
- 树的节点数在
[1, 10^4]范围内 0 <= Node.val <= 10^4
解题思路
这道题是典型的树形动态规划问题。对于每一个节点,我们面临两种选择:打劫当前节点,或者不打劫当前节点。
- 打劫当前节点:那么它的左右子节点都不能打劫。此时最大金额为当前节点的值加上左右子节点'不打劫'时的最大值。
- 不打劫当前节点:那么它的左右子节点可以打劫,也可以不打劫。为了收益最大化,我们分别取左右子节点'打劫'和'不打劫'中的较大值相加。
我们需要通过后序遍历(递归)自底向上地计算这两种状态的最大值。
代码实现
下面是基于 C 语言的实现,定义了二叉树节点结构,并通过辅助函数递归计算状态。
#include <stdio.h>
#include <stdlib.h>
// 定义二叉树的节点结构体
struct TreeNode {
int val;
struct TreeNode* left;
struct * ;
};
TreeNode* {
( TreeNode*)(( TreeNode));
node->val = val;
node->left = ;
node->right = ;
node;
}
{
(root == ) {
*robThisNode = ;
*notRobThisNode = ;
;
}
leftRob, leftNotRob;
rightRob, rightNotRob;
helper(root->left, &leftRob, &leftNotRob);
helper(root->right, &rightRob, &rightNotRob);
*robThisNode = root->val + leftNotRob + rightNotRob;
*notRobThisNode = (leftRob > leftNotRob ? leftRob : leftNotRob) +
(rightRob > rightNotRob ? rightRob : rightNotRob);
(*robThisNode > *notRobThisNode ? *robThisNode : *notRobThisNode);
}
{
robThisNode, notRobThisNode;
helper(root, &robThisNode, ¬RobThisNode);
(*robThisNode > *notRobThisNode ? *robThisNode : *notRobThisNode);
}


