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 1

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

Example 2:

     3
/ \
4 5
/ \ \
1 3 1

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

Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.

198. House Robber 和 213. House Robber II 的拓展,这回小偷又找了一个新的偷盗场所。这片区域只有一个入口,叫做“根”。除了根以外,每一个房间有且仅有一个父级房间。在踩点之后,聪明的盗贼发现“所有的房间形成了一棵二叉树”。如果两个有边直接相连的房间在同一晚上都失窃,就会自动联络警察。求在不惊动警察的情况下最多可以偷到的钱数。

Java: 递归穷举。比较本节点与孙节点之和、儿节点之和之间取最者。

public int rob(TreeNode root) {
if (root == null) return 0;
int val = 0;
if(root.left!=null){
val += rob(root.left.left);
val += rob(root.left.right);
}
if(root.right!=null){
val += rob(root.right.left);
val += rob(root.right.right);
}
return Math.max(val+root.val,(rob(root.left)+rob(root.right)));
}

Java: 改进递归,节省每一步计算中间值,因为儿节点又是孙节点的父节点,会重复计算,所以把计算的中间值存储到hash表中。

public int get(TreeNode root,HashMap<TreeNode,Integer> map) {
if (root == null) return 0;
if (map.containsKey(root)) return map.get(root);
int val = 0;
if(root.left!=null){
val += get(root.left.left,map);
val += get(root.left.right,map);
}
if(root.right!=null){
val += get(root.right.left,map);
val += get(root.right.right,map);
}
int x = Math.max(val+root.val,(get(root.left,map)+get(root.right,map)));
map.put(root,x);
return x; public int rob(TreeNode root) {
return get(root,new HashMap<TreeNode,Integer>());
}

Java: 对每个节点增加存储信息的位置,降低运算时间。

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/ class Solution {
public int[] get(TreeNode n){
if(n==null) return new int[2];
int[] lstrategy = get(n.left);//0表示不取,1表示取
int[] rstrategy = get(n.right);//
int[] nstrategy = new int[2];
nstrategy[0] = Math.max(lstrategy[0],lstrategy[1])+Math.max(rstrategy[0],rstrategy[1]); ; //strategy[0]表式不取本节点的策略取值,strategy[1]表式取本节点与孙节点的策略取值
nstrategy[1] = n.val + lstrategy[0] + rstrategy[0];
return nstrategy;
} public int rob(TreeNode root) {
if (root == null) return 0;
int[] result = get(root);
return Math.max(result[0],result[1]);
}
}

Java:

public class Solution {
public int rob(TreeNode root) {
int[] num = dfs(root);
return Math.max(num[0], num[1]);
}
private int[] dfs(TreeNode x) {
if (x == null) return new int[2];
int[] left = dfs(x.left);
int[] right = dfs(x.right);
int[] res = new int[2];
res[0] = left[1] + right[1] + x.val;
res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
return res;
}
}  

Python:

class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
def robHelper(root):
if not root:
return (0, 0)
left, right = robHelper(root.left), robHelper(root.right)
return (root.val + left[1] + right[1], max(left) + max(right)) return max(robHelper(root))

C++:

class Solution {
public:
int rob(TreeNode* root) {
unordered_map<TreeNode*, int> m;
return dfs(root, m);
}
int dfs(TreeNode *root, unordered_map<TreeNode*, int> &m) {
if (!root) return 0;
if (m.count(root)) return m[root];
int val = 0;
if (root->left) {
val += dfs(root->left->left, m) + dfs(root->left->right, m);
}
if (root->right) {
val += dfs(root->right->left, m) + dfs(root->right->right, m);
}
val = max(val + root->val, dfs(root->left, m) + dfs(root->right, m));
m[root] = val;
return val;
}
};

C++:

class Solution {
public:
int rob(TreeNode* root) {
vector<int> res = dfs(root);
return max(res[0], res[1]);
}
vector<int> dfs(TreeNode *root) {
if (!root) return vector<int>(2, 0);
vector<int> left = dfs(root->left);
vector<int> right = dfs(root->right);
vector<int> res(2, 0);
res[0] = max(left[0], left[1]) + max(right[0], right[1]);
res[1] = left[0] + right[0] + root->val;
return res;
}
};

C++:

class Solution {
public:
int rob(TreeNode* root) {
int l = 0, r = 0;
return helper(root, l, r);
}
int helper(TreeNode* node, int& l, int& r) {
if (!node) return 0;
int ll = 0, lr = 0, rl = 0, rr = 0;
l = helper(node->left, ll, lr);
r = helper(node->right, rl, rr);
return max(node->val + ll + lr + rl + rr, l + r);
}
};

  

类似题目:

[LeetCode] 198. House Robber 打家劫舍

[LeetCode] 213. House Robber II 打家劫舍 II

  

All LeetCode Questions List 题目汇总

[LeetCode] 337. House Robber III 打家劫舍 III的更多相关文章

  1. Leetcode 337. House Robber III

    337. House Robber III Total Accepted: 18475 Total Submissions: 47725 Difficulty: Medium The thief ha ...

  2. [LeetCode] 213. House Robber II 打家劫舍 II

    Note: This is an extension of House Robber. After robbing those houses on that street, the thief has ...

  3. [LeetCode] 337. House Robber III 打家劫舍之三

    The thief has found himself a new place for his thievery again. There is only one entrance to this a ...

  4. Java [Leetcode 337]House Robber III

    题目描述: The thief has found himself a new place for his thievery again. There is only one entrance to ...

  5. 337 House Robber III 打家劫舍 III

    小偷又发现一个新的可行窃的地点. 这个地区只有一个入口,称为“根”. 除了根部之外,每栋房子有且只有一个父房子. 一番侦察之后,聪明的小偷意识到“这个地方的所有房屋形成了一棵二叉树”. 如果两个直接相 ...

  6. LeetCode 337. House Robber III 动态演示

    每个节点是个房间,数值代表钱.小偷偷里面的钱,不能偷连续的房间,至少要隔一个.问最多能偷多少钱 TreeNode* cur mp[{cur, true}]表示以cur为根的树,最多能偷的钱 mp[{c ...

  7. [LeetCode] 213. House Robber II 打家劫舍之二

    You are a professional robber planning to rob houses along a street. Each house has a certain amount ...

  8. leetcode 198. House Robber 、 213. House Robber II 、337. House Robber III 、256. Paint House(lintcode 515) 、265. Paint House II(lintcode 516) 、276. Paint Fence(lintcode 514)

    House Robber:不能相邻,求能获得的最大值 House Robber II:不能相邻且第一个和最后一个不能同时取,求能获得的最大值 House Robber III:二叉树下的不能相邻,求能 ...

  9. Java实现 LeetCode 337 打家劫舍 III(三)

    337. 打家劫舍 III 在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区.这个地区只有一个入口,我们称之为"根". 除了"根"之外,每 ...

随机推荐

  1. Kotlin反射实践操作详解

    继续对反射进行实战. 获取构造方法: 先定义一个主构造方法,2个次构造方法,接下来咱们用反射来获取一下构造方法: 其结果: [fun <init>(kotlin.Int, kotlin.S ...

  2. Educational Codeforces Round 64 (Rated for Div. 2)题解

    Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...

  3. Linux代理服务器使用

    1. 介绍 代理(即网络代理)是一种特殊的网络服务, 允许一个网络终端(客户端)通过这个服务与另一个终端(服务器)进行非直接连接,从而提供服务. 其中, 提供代理的网络终端称为代理服务器(Proxy ...

  4. test20190926 孙耀峰

    70+100+0=170.结论题自己还是要多试几组小数据.这套题还不错. ZYB建围墙 ZYB之国是特殊的六边形构造. 已知王国一共有

  5. 做阉割版Salesforce难成伟大的TOB企业

    https://www.lieyunwang.com/archives/446227 猎云注:当前中国市场环境下,有没有可能诞生一批SaaS级企业服务公司?东方富海合伙人陈利伟用三个方面基础性问题解答 ...

  6. python 生成文件到- execl

    查了一些资料发现是英文版本的 很尴尬,经过看源码,和几个错误 ,现记录下来 一:下载包 pip install xlwt 二:定义样式 def set_style(name, height, bold ...

  7. SVN 常用 还原项目

    1.先修改本来两个文件,然后再提交到SVN 2.在日志界面,查看提交的文件,找到对应的版本号 3.找到对应的版本号(这里的版本号是1995,我提交生成的版本号 的前一个版本 才是我未作出修改的版本), ...

  8. [HAOI2015]树上染色 树状背包 dp

    #4033. [HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白 ...

  9. 洛谷P4380 [USACO18OPEN]Multiplayer Moo

    题目 第一问: 用广搜类似用\(floodfill\)的方法. 第二问: 暴力枚举加剪枝,对于每个连通块,枚举跟这个连通块相连的其他与他颜色不同的连通块,然后向外扩展合并颜色与他们俩相同的连通块.扩展 ...

  10. Bacteria(优先队列)

    题目链接:http://codeforces.com/gym/101911/problem/C 问题简述:给定n个细胞以及每个细胞的大小,相同的细胞能进行融合,如果能融合到只剩1个细胞则输出需要额外增 ...