zoukankan      html  css  js  c++  java
  • [LeetCode] 337. House Robber 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

      3
     / 
    2   3
         
      3   1
    

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

        3
       / 
      4   5
     /     
    1   3   1
    

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

     

    Unlike House Robber I && II,  this problem does not have a linear structure. Since it has a binary tree 

    in this problem, we should naturally think about solving the subproblems recursively before solving the

    original problem. 

     

    Optimal substructure:

    f(node) = Math.max(node.val + f(node.left.left) + f(node.left.right) + f(node.right.left) + f(node.right.right),  //choose node

              f(node.left) + f(node.right));  //not choose node

    With this formula, we have the following TLE solution.

    Why TLE? Think about BUD(bottlenecks, unnecessary work, duplicated work)

    To calculate f(node), we need to calculate f(node.left), f(node.right), f(node.left.left), f(node.left.right), f(node.right.left), f(node.right.right);

    To calculate f(node.left), we'll calculate f(node.left.left) and f(node.left.right) again; This duplication pattern applies to each node.

    So we have the overlapping subproblem issue.

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

     

    To avoid duplicated calculations, we apply the memoization search concept.  For each node, we save the intermediate result

    with choosing the current node and without choosing the current node.

    Essentially this solution applies the dynamic programming principle. We use the top-down memoization search since the it 

    is hard to find a proper init state and recurring bottom up is difficult for binary tree. The natural access fashion for any tree

    structure is top down.

     1 /**
     2  * Definition of TreeNode:
     3  * public class TreeNode {
     4  *     public int val;
     5  *     public TreeNode left, right;
     6  *     public TreeNode(int x) { val = x; }
     7  * }
     8  */
     9 public class Solution {
    10     private class ResultType{
    11         int maxWithCurrNode;
    12         int maxWithoutCurrNode;
    13         ResultType(int v1, int v2){
    14             maxWithCurrNode = v1;
    15             maxWithoutCurrNode = v2;
    16         }
    17     }
    18     public int houseRobber3(TreeNode root) {
    19         ResultType result = dfs(root);
    20         return Math.max(result.maxWithCurrNode, result.maxWithoutCurrNode);
    21     }
    22     private ResultType dfs(TreeNode node){
    23         if(node == null){
    24             return new ResultType(0, 0);
    25         }
    26         ResultType left = dfs(node.left);
    27         ResultType right = dfs(node.right);
    28         ResultType curr = new ResultType(0, 0);
    29         curr.maxWithCurrNode = left.maxWithoutCurrNode + right.maxWithoutCurrNode + node.val;
    30         curr.maxWithoutCurrNode = Math.max(left.maxWithoutCurrNode, left.maxWithCurrNode)
    31                                 + Math.max(right.maxWithoutCurrNode, right.maxWithCurrNode);
    32         return curr;
    33     }
    34 }

     

     

    Related Problems

    Binary Tree Maximum Path Sum

  • 相关阅读:
    2011年需要关注的9大编程语言 狼人:
    微软在华推广Win7拒绝“黑屏” 狼人:
    ifanr访谈:GuruDigger — Web工程师排排坐 狼人:
    10种破除网页设计师障碍的实用方法 狼人:
    英特尔CEO:微软Windows 7是PC更新的催化剂 狼人:
    Windows 7市场份额突破25% XP持续下滑 狼人:
    Office Web Apps中文版正式上线 狼人:
    机器学习实现线性梯度算实现octave
    管理系统数据库sql server 数据库管理
    缓存代码sencha Touch 缓存问题解析
  • 原文地址:https://www.cnblogs.com/lz87/p/6955071.html
Copyright © 2011-2022 走看看