题目描述:https://leetcode.com/problems/house-robber-iii/
一开始被描述中的例子误导了,觉得应该只能打劫间隔的一层,所以写了一个层次遍历,计算每一层的和再决定怎么打劫。后来发现是不对的,因为可以打劫左子树而不打劫右子树,如树[2,7,1,null,4,null,8]
对于二叉树中的某一个节点i,它也有偷与不偷这两个选项,若偷,则两个子节点不能偷;否则,两个子节点可以偷。与I、II不同的是,I、II中对当前的房屋i,偷与不偷仅需把其中的较大者保留下来进行,因为后续的结果均是建立在前者为最优解的基础上进行的,而且DP[i] = max{DP[i-1],DP[i-2]+A[i]}一定能保证不发生冲突;但是对于二叉树,当前节点i并不能那么方便的找到其子节点的子节点的最优解,因此并不能同I、II那样仅记录最优解。对于二叉树的节点而言,其最容易访问到的就是它的两个子节点。因此,可以建立一个大小为2的一维数组DP,其中DP[0]用来记录偷当前节点所能获利值,DP[1]用来记录不偷当前的值所能获利的值。使用递归的方法求解。
class Solution {
public:
int rob(TreeNode* root) {
vector<int> res=helper(root);
return max(res[0],res[1]);
}
vector<int> helper(TreeNode* root){
vector<int> res={0,0};
if (root==NULL) return res;
//得到打劫或者不打劫左子树的结果
vector<int> left=helper(root->left);
//得到打劫或者不打劫右子树的结果
vector<int> right=helper(root->right);
//打劫根节点则不打劫左右子树
res[0]=left[1]+right[1]+root->val;
//否则计算左右子树可以打劫时的最大情况
res[1]=max(left[0],left[1])+max(right[1],right[0]);
return res;
}
};