• 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 }
  • 相关阅读:
    云计算和大数据时代网络技术揭秘(十九)万兆革命 (完)
    云计算和大数据时代网络技术揭秘(十八)刀片服务器的网络
    云计算和大数据时代网络技术揭秘(十七)VOQ机制
    云计算和大数据时代网络技术揭秘(十六)数据中心布线
    云计算和大数据时代网络技术揭秘(十五)大数据网络
    云计算和大数据时代网络技术揭秘(十四)虚拟桌面
    云计算和大数据时代网络技术揭秘(十三)VXLAN
    python3练习100题——037
    python3练习100题——036
    python3练习100题——035
  • 原文地址:https://www.cnblogs.com/nilbook/p/13443817.html
Copyright © 2020-2023  润新知