本道题转化为动规的关键点在于:当前结点偷与否,与两个孩子结点有关系。
在二叉树中,可以使用后序遍历,先遍历两个子节点,再到根结点,根结点根据子节点是否偷,再决定当前结点。
所以这里的每个结点有两个状态 偷(1 还是 不偷(0,对应一个一维数组
写一个递归函数,返回值为 一维数组,对应的就是当前结点偷和不偷,所对应的金币数。
递推公式:
偷:root->val + left[0] + right[0]
这里就表示将根结点偷取,而两个子节点不偷取
不偷:max(left[0], left[1]) + max(right[0], right[1])、
表示根结点不偷取,两个子节点选取金币数最大的状态( 0 或 1 )
class Solution {
public:
vector<int> robtree(TreeNode* root)
{
if(root == nullptr)
return {0,0};
// 接住上层返回的一维数组,两个子树都有 对应偷和不偷两种状态
vector<int> left = robtree(root->left);
vector<int> right = robtree(root->right);
// 不取当前结点
int val1 = max(left[0], left[1]) + max(right[0], right[1]);
// 取
int val2 = root->val + left[0] + right[0];
// 返回给根结点
return {val1, val2};
}
int rob(TreeNode* root) {
vector<int> res = robtree(root);
return max(res[0], res[1]);
}
};