LeetCode 337. House Robber III

Question

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.33

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Input: [3,2,3,null,3,null,1]

*3
/ \
2 3
\ \
*3 *1

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


Input: [3,4,5,1,3,null,1]

3
/ \
*4 *5
/ \ \
1 3 1

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

Solution

因为这是一个tree的问题,所以首先想到的应该是用递归的方法解决。

  • Solution1:这个问题与之前的i和ii没有太大区别,都是当前被偷之后,邻接的下一层无法被选择。假设我选择当前这一层,那么我可以选择递归调用下下层的所有节点,即root.left.left, root.left.right, root.right.left, root.right.left,然后让当前选择的值加上其下下层的值与取下一层的递归值进行比较。其中,我们采取HashMap进行缓存优化。
  • Solution2:依然是采取递归的思路,设置返回值为二维数组,其中第0个位置代表不抢当前值,第1个位置表示抢当前值。计算的过程中,我们采取后序遍历,对于左右子树返回的值进行处理,情况和上面一致。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// DP + Memo.
public static int rob(TreeNode root) {
if (root == null) return 0;
HashMap<TreeNode, Integer> map = new HashMap<>();
return helper(root, map);
}
// time:O(n) space:O(n)
public static int helper(TreeNode root, HashMap<TreeNode, Integer> map) {
if (map.get(root) != null) return map.get(root);
if (root == null) return 0;
int sumOfChose = 0;
if (root.left != null) {
sumOfChose += helper(root.left.left, map) + helper(root.left.right, map);
}
if (root.right != null) {
sumOfChose += helper(root.right.left, map) + helper(root.right.right, map);
}
sumOfChose += root.val;
int sumOfNotChose = helper(root.left, map) + helper(root.right, map);
int res = Math.max(sumOfChose, sumOfNotChose);
map.put(root, res);
return res;
}
// 利用二维数组 第0位代表不偷,第一位代表偷。
public int rob2(TreeNode root) {
if (root == null) return 0;
int[] res = helper(root);
return Math.max(res[0], res[1]);
}

public int[] helper(TreeNode root) {
if (root == null) return new int[]{0, 0};
int[] res = new int[2];
int[] left = helper(root.left);
int[] right = helper(root.right);
// 当前节点不偷的话
res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
// 当前节点偷的话
res[1] = root.val + left[0] + right[0];

return res;
}

Reference