本系列使用IDEA+LEETCODE EDITOR插件,题目描述统一英文。
题目链接
一、题目描述:
//The thief has found himself a new place for his thievery again. There is only
//one entrance to this area, called 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 form a binary tree. It w
//ill automatically contact the police if two directly-linked houses were broken i
//nto on the same night.
//
// Given the root of the binary tree, return the maximum amount of money the thi
//ef can rob without alerting the police.
//
//
// Example 1:
//
//
//Input: root = [3,2,3,null,3,null,1]
//Output: 7
//Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
//
//
// Example 2:
//
//
//Input: root = [3,4,5,1,3,null,1]
//Output: 9
//Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.
//
//
//
// Constraints:
//
//
// The number of nodes in the tree is in the range [1, 104].
// 0 <= Node.val <= 104
二、思路分析:
首先可以复习下之前的2种非相邻数最大和问题的解题思路。
非相邻数最大和原型。
非相邻数最大和变种1。
这道题又有了新的变化,从之前的数组-首位衔接的数组-二叉树。
一开始我走进了思维误区,认为这不就是一个BFS算法么,对二叉树进行层序遍历然后针对每层的数做非相邻数最大和计算。然后发现我错了,因为我没理解题目真正的要求。
现在跟我一起认真读题,不要走我踩过的坑:
对一个小偷来说,一旦抢了树的一个节点,意味着这个节点的左右直接子节点都不能抢了,而下一个能抢的要在这个节点的左右直接子节点的各自个子节点。
比如这样的树,1,2,3,4,5,6,7。当选择了偷1之后,2,3就不能偷了,但是接下来可以偷的是2的子节点4,5全部,和3的左右子节点6,7全部。
这里就可以找到为什么我之前的解法错了,对一个节点来说,当左子树决定选自己的时候,对右子树来说可不是一定的了,右子树可以放弃当前层去偷它的两个子节点。
当变种题目给出了新的数据结构,如何识别到新结构对之前解题框架的影响,这才是本期的重点。
三、AC 代码:
class Solution {
// 用于剪枝,存节点和到该节点能抢的最大值
Map<TreeNode,Integer> map = new HashMap<>();
public int rob(TreeNode root) {
// 递归终止条件
if(root == null){
return 0;
}
// 剪枝
if(map.containsKey(root)){
return map.get(root);
}
// 开始判断抢当前还是不抢当前节点
// 抢当前的就是当前值加上抢当前节点左的子节点和当前节点右的子节点
int robbed = root.val + (root.left==null?0:(rob(root.left.left)+rob(root.left.right))) + (root.right==null?0:(rob(root.right.left)+rob(root.right.right)));
// 不抢当前的,就是抢当前节点的子节点
int skip = rob(root.left)+rob(root.right);
int result = Math.max(robbed,skip);
map.put(root,result);
return result;
}
}
解答成功:
执行耗时:3 ms,击败了58.71% 的Java用户
内存消耗:38 MB,击败了85.01% 的Java用户
四、总结:
- 遇到变种题把原型的数据结构都给变了,要思考总结新的数据结构会引起哪些变化。
- 写完代码后一定要进行自测,看是否符合预期。
- 逢递归,必剪枝。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情