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 1:

    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.

    Example 2:

    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.

    打家劫舍III。题意跟前两个版本差不多,但是这次,小偷的目标换到一棵树了。给了一个树的根节点root,规则是不能偷相邻两层的节点上的房子。问最大收益是多少。

    我这里提供几种思路,代码执行速度由慢到快,都值得掌握。我参考了这个帖子

    首先是比较朴素的递归。思路是如果偷了根节点的房子,则不能偷儿子节点。最后判断的是到底是从根节点偷的收益大还是从儿子节点偷的收益大。

    时间O(n)

    空间O(n)

    Java实现

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

    再来是记忆化递归。第一种解法中间有很多重复计算,需要用hashmap把中间过程的值记录下来。

    时间O(n)

    空间O(n)

    Java实现

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

    最后是动态规划。创建一个数组,res[0]表示不偷当前节点,res[1]表示偷当前节点。

    时间O(n)

    空间O(n)

    Java实现

     1 class Solution {
     2     public int rob(TreeNode root) {
     3         int[] res = helper(root);
     4         // 当前节点不偷,偷
     5         return Math.max(res[0], res[1]);
     6     }
     7     
     8     private int[] helper(TreeNode root) {
     9         if (root == null) {
    10             return new int[2];
    11         }
    12         int[] left = helper(root.left);
    13         int[] right = helper(root.right);
    14         int[] res = new int[2];
    15         res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
    16         res[1] = root.val + left[0] + right[0];
    17         return res;
    18     }
    19 }

    LeetCode 题目总结

  • 相关阅读:
    改变,必须改变
    厦门四日
    再谈兴趣的重要性,人的差别及如何认识自我
    xcode svn checkout的项目无法真机运行解决办法
    [转]c的fopen()打开文件的模式,第二个参数
    cocos2dx 横板游戏触屏人物和背景移动 方法1
    简单的小球移动隐含的bug
    使用CCHttpRequest后要记得release(),否则内存泄漏
    资源路径问题 (ios平台)
    cocos2dx 横板游戏触屏人物和背景移动 方法2
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13437340.html
Copyright © 2011-2022 走看看