思路
本题要求tree中相邻node有限制条件,是此类题目的典型。
-
不知道当前节点是否被使用,且在向下递归的过程中,之前节点是否被使用过的信息会丢失,因此,在参数中传递一个used参数,保存此信息。used为true,说明使用了root节点,否则,没使用root节点。当使用root节点时,root的两个子节点不能使用,当没使用root节点时,两个子节点可用可不用。
-
与第一种方法大同小异,只不过每次递归时,将使用root和不使用root两种情况都检查了,然后返回最大值。返回的结果总是符合相邻节点间的限制,因此不会在返回递归时,不会违背该限制。
-
前两种方法通过unordered_map防止超时。第三种方法通过传引用的方式提速。事实证明,很多时候通过传引用的方式,表现更好。
代码
方法1
class Solution {
public:
int rob(TreeNode* root) {
unordered_map<TreeNode*, int> useMap;
unordered_map<TreeNode*, int> unUseMap;
return max(DFS(root, true, useMap, unUseMap), DFS(root,false, useMap, unUseMap));
}
int DFS (TreeNode* root, bool used, unordered_map<TreeNode*, int> &useMap, unordered_map<TreeNode*, int> &unUseMap) {
if (!root) return 0;
int useLeft = 0, useRight = 0, unUseLeft = 0, unUseRight = 0;
if (useMap.count(root->left))
useLeft = useMap[root->left];
else {
useLeft = DFS(root->left, true, useMap, unUseMap);
useMap[root->left] = useLeft;
}
if (useMap.count(root->right))
useRight = useMap[root->right];
else {
useRight = DFS(root->right, true, useMap, unUseMap);
useMap[root->right] = useRight;
}
if (unUseMap.count(root->left))
unUseLeft = unUseMap[root->left];
else {
unUseLeft = DFS(root->left, false, useMap, unUseMap);
unUseMap[root->left] = unUseLeft;
}
if (unUseMap.count(root->right))
unUseRight = unUseMap[root->right];
else {
unUseRight = DFS(root->right, false, useMap, unUseMap);
unUseMap[root->right] = unUseRight;
}
if (used)
return root->val + unUseLeft + unUseRight;
else
return max(useLeft, unUseLeft) + max(useRight, unUseRight);
}
};
### 方法2
class Solution {
public:
int rob(TreeNode* root) {
unordered_map<TreeNode*, int> mp;
return rob(root, mp);
}
int rob (TreeNode *root, unordered_map<TreeNode*, int> &mp) {
if (!root) return 0;
if (mp.count(root)) return mp[root];
int sum = 0;
if (root->left)
sum += rob(root->left->left, mp) + rob(root->left->right, mp);
if (root->right)
sum += rob(root->right->left, mp) + rob(root->right->right, mp);
sum = max(sum + root->val, rob(root->left, mp) + rob(root->right, mp));
mp[root] = sum;
return sum;
}
};
方法3
class Solution {
public:
int rob(TreeNode* root) {
int withMe, withoutMe;
withMe = withoutMe = 0;
maxMoney(root, withMe, withoutMe);
return max(withMe, withoutMe);
}
void maxMoney(TreeNode* root, int &withMe, int &withoutMe) {
int wMeL, woMeL; // max money robbed: (with/without me for left child)
int wMeR, woMeR; // max money robbed: (with/without me for right child)
if (!root)
return;
wMeL = woMeL = wMeR = woMeR = 0;
maxMoney(root->left, wMeL, woMeL);
maxMoney(root->right, wMeR, woMeR);
withMe = woMeL + woMeR + root->val;
withoutMe = max(wMeL, woMeL) + max(wMeR, woMeR);
}
};