[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.
这次小偷偷的是一个二叉树型的小区,触发报警器的条件依然是相邻的房子同时失窃,即直接相连的两个节点(房子)同时失窃,问如何在不触发报警的条件下,能偷窃的最大金额。
该题是House Robber I 和House Robber II 的拓展,依然可以利用动态规划的方法解决此题。具体思路如下:
对于根节点而言,有两种状态:偷,不偷。因此可以用一个数组maxMoney[2]来分别记录偷、不偷该根节点所能获得的最高价值
其中maxMoney[0]表示偷该节点所能获得的最高价值,maxMoney[1]表示不偷该节点所能获得的最高价值
二叉树常用分治法,可将根节点的问题,转化为左右子树的问题
分析可知,根节点的maxMoney[]数组是由其左右子树的leftMaxMoney[]和rightMaxMoney[]确定的
具体为:
maxMoney[0](偷) = leftMaxMoney[1](不偷左子节点) + rightMaxMoney[1](不偷右子节点) + root.val(偷该根节点)
maxMoney[1](不偷) = max(leftMaxMoney[0],leftMaxMoney[1]) + max(rightMaxMoney[0],rightMaxMoney[1])
class Solution { public int rob(TreeNode root) { int[] res = helper(root); return Math.max(res[0], res[1]); } /** * 对于根节点而言,有两种状态:偷,不偷。因此可以用一个数组maxMoney[2]来分别记录偷、不偷该根节点所能获得的最高价值 * 其中maxMoney[0]表示偷该节点所能获得的最高价值 * maxMoney[1]表示不偷该节点所能获得的最高价值 * 二叉树常用分治法,可将根节点的问题,转化为左右子树的问题 * 分析可知,根节点的maxMoney[]数组是由其左右子树的leftMaxMoney[]和rightMaxMoney[]确定的 * 具体为: * maxMoney[0](偷) = leftMaxMoney[1](不偷左子节点) + rightMaxMoney[1](不偷右子节点) + root.val(偷该根节点) * maxMoney[1](不偷) = max(leftMaxMoney[0],leftMaxMoney[1]) + max(rightMaxMoney[0],rightMaxMoney[1]) * @param root 根节点 * @return 数组maxMoney[2]分别记录以该节点位根,偷、不偷该根节点所能获得的最高价值 */ public int[] helper(TreeNode root) { if(root == null) { int[] maxMoney = new int[]{0,0}; return maxMoney; } int[] maxMoney = new int[2]; int[] leftMaxMoney = helper(root.left); int[] rightMaxMoney = helper(root.right); maxMoney[0] = leftMaxMoney[1] + rightMaxMoney[1] + root.val; maxMoney[1] = Math.max(leftMaxMoney[0],leftMaxMoney[1]) + Math.max(rightMaxMoney[0],rightMaxMoney[1]); return maxMoney; } }