【LeetCode】337. House Robber III 打家劫舍 III(Medium)(JAVA)
题目地址: https://leetcode.com/problems/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.
题目大意
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
解题方法
暴力求解
- 直接暴力每个都判断当前是否需要偷;如果当前偷,下一个就不能再偷,如果当前不偷,下一个就可以偷
- 每次都需要遍历子树两次
class Solution {
public int rob(TreeNode root) {
return robHelp(root, true);
}
public int robHelp(TreeNode root, boolean canRob) {
if (root == null) return 0;
if (canRob) {
return Math.max(robHelp(root.left, true) + robHelp(root.right, true), root.val + robHelp(root.left, false) + robHelp(root.right, false));
} else {
return robHelp(root.left, true) + robHelp(root.right, true);
}
}
}
执行耗时:1546 ms,击败了5.00% 的Java用户
内存消耗:38.5 MB,击败了36.54% 的Java用户
优化
- 暴力方法对子树每次都遍历了两遍,造成越往下,遍历的次数是指数增长的,所以想办法能不能遍历一次就把偷和不偷的结果都返回呢?
- 这样需要返回值是一个数组(同时返回偷和不偷的结果)
- 如果偷的话,子树肯定就不能偷了,就是 root.val + function(roo.left)[不偷] + …;
- 如果不偷,那子树既可以偷也可以不偷,取两个的最大值,Math.max(function(root.left)[偷], function(root.left)[不偷])
class Solution {
public int rob(TreeNode root) {
int[] res = robHelp(root);
return Math.max(res[0], res[1]);
}
// int[0]: rob; int[1]: not rob
public int[] robHelp(TreeNode root) {
if (root == null) return new int[]{0, 0};
int[] left = robHelp(root.left);
int[] right = robHelp(root.right);
return new int[]{left[1] + right[1] + root.val, Math.max(left[0], left[1]) + Math.max(right[0], right[1])};
}
}
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:38.3 MB,击败了58.62% 的Java用户
![](https://i-blog.csdnimg.cn/blog_migrate/6c56d31f951aece27c5faae608dfac2e.jpeg)