### [LeetCode] 337. House Robber III 打家劫舍 III

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example 1:

```     3
/ \
2   3
\   \
3   1
```

Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2:

```     3
/ \
4   5
/ \   \
1   3   1
```

Maximum amount of money the thief can rob = 4 + 5 = 9.

Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.

198. House Robber 和 213. House Robber II 的拓展，這回小偷又找了一個新的偷盜場所。這片區域只有一個入口，叫做“根”。除了根以外，每一個房間有且僅有一個父級房間。在踩點之后，聰明的盜賊發現“所有的房間形成了一棵二叉樹”。如果兩個有邊直接相連的房間在同一晚上都失竊，就會自動聯絡警察。求在不驚動警察的情況下最多可以偷到的錢數。

Java: 遞歸窮舉。比較本節點與孫節點之和、兒節點之和之間取最者。

```public int rob(TreeNode root) {
if (root == null) return 0;
int val = 0;
if(root.left!=null){
val += rob(root.left.left);
val += rob(root.left.right);
}
if(root.right!=null){
val += rob(root.right.left);
val += rob(root.right.right);
}
return Math.max(val+root.val,(rob(root.left)+rob(root.right)));
}
```

Java: 改進遞歸，節省每一步計算中間值，因為兒節點又是孫節點的父節點，會重復計算，所以把計算的中間值存儲到hash表中。

```public int get(TreeNode root,HashMap<TreeNode,Integer> map) {
if (root == null) return 0;
if (map.containsKey(root)) return map.get(root);
int val = 0;
if(root.left!=null){
val += get(root.left.left,map);
val += get(root.left.right,map);
}
if(root.right!=null){
val += get(root.right.left,map);
val += get(root.right.right,map);
}
int x = Math.max(val+root.val,(get(root.left,map)+get(root.right,map)));
map.put(root,x);
return x;

public int rob(TreeNode root) {
return get(root,new HashMap<TreeNode,Integer>());
}
```

Java: 對每個節點增加存儲信息的位置，降低運算時間。

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/

class Solution {
public int[] get(TreeNode n){
if(n==null) return new int[2];
int[] lstrategy = get(n.left);//0表示不取，1表示取
int[] rstrategy = get(n.right);//
int[] nstrategy = new int[2];
nstrategy[0] = Math.max(lstrategy[0],lstrategy[1])+Math.max(rstrategy[0],rstrategy[1]); ; //strategy[0]表式不取本節點的策略取值,strategy[1]表式取本節點與孫節點的策略取值
nstrategy[1] = n.val + lstrategy[0] + rstrategy[0];
return nstrategy;
}

public int rob(TreeNode root) {
if (root == null) return 0;
int[] result = get(root);
return Math.max(result[0],result[1]);
}
}
```

Java:

```public class Solution {
public int rob(TreeNode root) {
int[] num = dfs(root);
return Math.max(num[0], num[1]);
}
private int[] dfs(TreeNode x) {
if (x == null) return new int[2];
int[] left = dfs(x.left);
int[] right = dfs(x.right);
int[] res = new int[2];
res[0] = left[1] + right[1] + x.val;
res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
return res;
}
}　　```

Python:

```class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
def robHelper(root):
if not root:
return (0, 0)
left, right = robHelper(root.left), robHelper(root.right)
return (root.val + left[1] + right[1], max(left) + max(right))

return max(robHelper(root))
```

C++:

```class Solution {
public:
int rob(TreeNode* root) {
unordered_map<TreeNode*, int> m;
return dfs(root, m);
}
int dfs(TreeNode *root, unordered_map<TreeNode*, int> &m) {
if (!root) return 0;
if (m.count(root)) return m[root];
int val = 0;
if (root->left) {
val += dfs(root->left->left, m) + dfs(root->left->right, m);
}
if (root->right) {
val += dfs(root->right->left, m) + dfs(root->right->right, m);
}
val = max(val + root->val, dfs(root->left, m) + dfs(root->right, m));
m[root] = val;
return val;
}
};
```

C++:

```class Solution {
public:
int rob(TreeNode* root) {
vector<int> res = dfs(root);
return max(res[0], res[1]);
}
vector<int> dfs(TreeNode *root) {
if (!root) return vector<int>(2, 0);
vector<int> left = dfs(root->left);
vector<int> right = dfs(root->right);
vector<int> res(2, 0);
res[0] = max(left[0], left[1]) + max(right[0], right[1]);
res[1] = left[0] + right[0] + root->val;
return res;
}
};
```

C++:

```class Solution {
public:
int rob(TreeNode* root) {
int l = 0, r = 0;
return helper(root, l, r);
}
int helper(TreeNode* node, int& l, int& r) {
if (!node) return 0;
int ll = 0, lr = 0, rl = 0, rr = 0;
l = helper(node->left, ll, lr);
r = helper(node->right, rl, rr);
return max(node->val + ll + lr + rl + rr, l + r);
}
};
```

[LeetCode] 198. House Robber 打家劫舍

[LeetCode] 213. House Robber II 打家劫舍 II