LeedCode刷题:337.打家劫舍Ⅲ

由题意知:

一、暴力法:

根结点是爷爷,根结点的左右孩子结点是两个孩子,孩子的孩子是孙子

所以比较四个孙子vs两个儿子 这两个组合谁得钱多,就当做当前结点的最大钱数,

4 个孙子投的钱加上爷爷的钱如下
int method1 = root.val + rob(root.left.left) + rob(root.left.right) + rob(root.right.left) + rob(root.right.right)
两个儿子偷的钱如下
int method2 = rob(root.left) + rob(root.right);
挑选一个钱数多的方案则
int result = Math.max(method1, method2);

 1 public int rob(TreeNode root) {
 2     if (root == null) return 0;
 3 
 4     int money = root.val;
 5     if (root.left != null) {
 6         money += (rob(root.left.left) + rob(root.left.right));
 7     }
 8 
 9     if (root.right != null) {
10         money += (rob(root.right.left) + rob(root.right.right));
11     }
12 
13     return Math.max(money, rob(root.left) + rob(root.right));
14 }

二、记忆化搜索

在方法一种,发现在计算爷爷时,已经计算了一次孙子的值,所以在儿子当爷爷时,会重复计算一遍孙子结点

所以我们把计算的值存下来,下次再用就直接从里面取出来,只需一次计算

因为二叉树不方便用数组,所以用哈希表存计算结果

 1       public int rob(TreeNode root) {
 2             HashMap<TreeNode,Integer> memo=new HashMap<>();
 3             return rob_2(root,memo);
 4     }
 5         public static int rob_2(TreeNode root,HashMap<TreeNode,Integer> memo){
 6             if(root==null)
 7                 return 0;
 8             if(memo.containsKey(root))
 9                 return memo.get(root);
10             int money=root.val;
11             if(root.left!=null){
12                 money+=(rob_2(root.left.left,memo)+rob_2(root.left.right,memo));
13             }
14             if(root.right!=null){
15                 money+=(rob_2(root.right.left,memo)+rob_2(root.right.right,memo));
16             }
17             int res=Math.max(money,rob_2(root.left,memo)+rob_2(root.right,memo));
18             memo.put(root,res);
19             return res;
20         }

三、最终

任何一个节点能偷到的最大钱的状态可以定义为

当前节点选择不偷:当前节点能偷到的最大钱数 = 左孩子能偷到的钱 + 右孩子能偷到的钱
当前节点选择偷:当前节点能偷到的最大钱数 = 左孩子选择自己不偷时能得到的钱 + 右孩子选择不偷时能得到的钱 + 当前节点的钱数

root[0] = Math.max(rob(root.left)[0], rob(root.left)[1]) + Math.max(rob(root.right)[0], rob(root.right)[1])
root[1] = rob(root.left)[0] + rob(root.right)[0] + root.val;

 1 public int rob(TreeNode root) {
 2     int[] result = robInternal(root);
 3     return Math.max(result[0], result[1]);
 4 }
 5 
 6 public int[] robInternal(TreeNode root) {
 7     if (root == null) return new int[2];
 8     int[] result = new int[2];
 9 
10     int[] left = robInternal(root.left);
11     int[] right = robInternal(root.right);
12 
13     result[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
14     result[1] = left[0] + right[0] + root.val;
15 
16     return result;
17 }

 

posted @ 2020-08-06 01:15  nilbook  阅读(124)  评论(0编辑  收藏  举报