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. hak的使用

    autohotkey简称ahk 它是一款轻量级的脚本语言文件,它可以干任何事情,如做dnf的连发脚本,类似按键精灵的自动化点击,按键自动打开文件一系列事情,文件需要按照ahk自己的语言,实现自定义的脚 ...

  2. GlusterFS Dispersed Volume(纠错卷)总结

    https://blog.csdn.net/daydayup_gzm/article/details/52748812 一.概念 Dispersed Volume是基于ErasureCodes(纠错码 ...

  3. vue之组件通信

    vue组件通信一般分为以下几种情况: 1.父子组件通信: 2.兄弟组件通信: 3.跨多层级组件通信: 一.父子通信        父组件通过props传递数据给子组件,子组件通过emit发送事件传递数 ...

  4. AtCoder Beginner Contest 125 解题报告

    那天晚上刚好有事就咕了. 最近的那一场E题还不会写.F题全场又只过了三个?留坑吧... A - Biscuit Generator #include <cstdio> using name ...

  5. C# 跨线程对控件赋值

    第一种 跨线程对控件赋值 private void button2_Click(object sender, EventArgs e) { Thread thread1 = new Thread(ne ...

  6. 编程用泰勒公式求e的近似值,直到最后一项小于10的负6次方为止。

    #include<stdio.h>#include<math.h>void main(){ int n; float j=1.0,sum=1.0; for(n=1;;n++) ...

  7. 10、Hadoop组件启动方式和SSH无密码登陆

    启动方式 一.各个组件逐一启动 hdfs: hadoop-daemon.sh start|stop namenode|datanode|secondnode yarn: yarn-demon.sh s ...

  8. Wideband Direction of Arrival Estimation Based on Multiple Virtual Extension Arrays

    基于多重虚拟扩展阵列的宽带信号DOA估计[1]. 宽带DOA估计是阵列信号处理领域的一个重要研究方向.在DOAs估计的实际应用中,信号总是会被噪声破坏,在某些情况下,源信号的数量大于传感器的数量,因此 ...

  9. LeetCode 457. Circular Array Loop

    原题链接在这里:https://leetcode.com/problems/circular-array-loop/ 题目: You are given a circular array nums o ...

  10. tomcat 配置域名证书

    tomcat 配置域名证书 示例: <!--" protocol="HTTP/1.1" connectionTimeout=" redirectPort= ...