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 1Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
3 / \ 4 5 / \ \ 1 3 1Maximum amount of money the thief can rob = 4 + 5 = 9.
通过读题可以发现:这是一个dp问题,如果将子问题设为,子树的max money。那么两种情况取最大值:1,root本身和root后第二层的节点maxmoney之和;2,root后第一层节点的maxmoney之和。
public int find(TreeNode x,HashMap<TreeNode, Integer> bag){
if(x==null)
return 0;
if(bag.containsKey(x))
return bag.get(x);
else {
int tt=search(x,bag);
bag.put(x, tt);
return tt;
}
}
public int search(TreeNode root,HashMap<TreeNode, Integer> bag) {
if(root==null)
return 0;
if(root.left==null&&root.right==null){
return root.val;
}else{
int twol=find(root.left,bag);
int twor=find(root.right,bag);
int threell=root.left==null?0:find(root.left.left,bag);
int threelr=root.left==null?0:find(root.left.right,bag);
int threerl=root.right==null?0:find(root.right.left,bag);
int threerr=root.right==null?0:find(root.right.right,bag);
return Math.max(root.val+threell+threelr+threerl+threerr,
twol+twor);
}
}
public int rob(TreeNode root) {
HashMap<TreeNode, Integer> bag=new HashMap<>();
return search(root,bag);
}
我的这种写法本来可以少一个函数,就是将hashmap设置成全局变量,但是那样的算法在java里面非常不容易维护的。因此使用hashmap作为参数,java中的参数都是引用,所以里面的值也是更改的。
还有一种更为巧妙地方法,时间复杂度没有变化,节省了hashmap的空间。这种能够方法每个节点设置了两个值,表示包含root节点的maxmoney和不包含的maxmoney,组后结果取两者最大值。
public int rob(TreeNode root) {
int[] res = robSub(root);
return Math.max(res[0], res[1]);
}
private int[] robSub(TreeNode root) {
if (root == null) {
return new int[2];
}
int[] left = robSub(root.left);
int[] right = robSub(root.right);
int[] res = new int[2];
res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
res[1] = root.val + left[0] + right[0];
return res;
}