###### tags: `LeetCode` `Recursion` `Tree` `Medium` `DFS`
# LeetCode #337 [House Robber III](https://leetcode.com/problems/house-robber-iii/)
### (Medium)
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了一個新的可行竊的地區。這個地區只有一個入口,我們稱之為“根”。除了“根”之外,每棟房子有且只有一個“父“房子與之相連。一番偵察之後,聰明的小偷意識到“這個地方的所有房屋的排列類似於一棵二元樹”。如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
---
每個節點都會回傳一組數組{with root, without root}代表搶劫該節點可獲得的最大利潤,以及不搶劫該節點可獲得的最大利潤。
同樣的, 以DFS方式先處理最底層節點, 並一次回傳, 最後回傳搶劫根結點與不搶劫根結點中利潤較大者。
```
class Solution {
public:
int rob(TreeNode* root) {
return max(tryrob(root)[0],tryrob(root)[1]);
}
vector<int> tryrob(TreeNode* node){
//{with root, without root}
if(!node)return {0,0};
vector<int> left=tryrob(node->left);
vector<int> right=tryrob(node->right);
vector<int> nodeval(2);
nodeval[0]=left[1]+right[1]+node->val;//with root
nodeval[1]=max(left[0],left[1])+max(right[0],right[1]);//without root
return nodeval;
}
};
```
---
LeetCode版本
核心概念相似, 只是利用參考的特性, 省去記憶體空間, 計算速度也更快。
```
class Solution {
public:
int tryRob(TreeNode* root, int& l, int& r) {
if (!root)
return 0;
int ll = 0, lr = 0, rl = 0, rr = 0;
l = tryRob(root->left, ll, lr);
r = tryRob(root->right, rl, rr);
return max(root->val + ll + lr + rl + rr, l + r);
}
int rob(TreeNode* root) {
int l, r;
return tryRob(root, l, r);
}
};
```