Problem: 337. 打家劫舍 III
1.构建多阶段决策模型:树形DP基于树这种数据结构上的推导,一般都是从上往下推,子节点状态推导父节点状态,一般都是基于后续遍历来实现。
2.定义状态:每个节点有两个状态;偷、不偷int moeny[2]表示每个节点的状态;money[0]表示选择不偷此节点,当下最大金额,money[1]表示选择偷此节点,当下最大金额。
3.定义状态转移方程:root.money[0] = max(left.money[0], left.money[1]) + max(right.money[0], right.money[1])即表示若当前节点选择不偷,则当前可以获得的最大金额为左右子节点的可偷或则不可偷的最大金额和;root.money[1] = left.money[0] + right.money[0] + root.val; 即表示若选择偷当前的节点则当前可以获得的最大金额为当前节点左右子节点均不偷可以获得的最大金额之和再加上当前偷取的金额
1.编写并调用int[]类型函数postorder(将其赋值给一个int[]数组名为money)
1.1若当前节点为null则返回一个int数组;
1.2递归处理:依次递归处理左子节点偷取最大金额、右子节点偷取最大金额;
1.2递归处理操作:实现上述动态转移方程。
2.返回最终数组money中的较大值max(money[0], money[1])
时间复杂度:
O ( n ) O(n) O(n);其中 n n n为二叉树的节点的个数
空间复杂度:
O ( l o g n ) O(logn) O(logn)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
* Get the maximum amount you can steal (tree DP)
*
* @param root
* @return int
*/
public int rob(TreeNode root) {
int[] money = postorder(root);
return Math.max(money[0], money[1]);
}
/**
* The next iteration gets the maximum amount that can be stolen
*
* @param root The root node of a binary tree
* @return int[]
*/
private int[] postorder(TreeNode root) {
if (root == null) {
return new int[]{0, 0};
}
int[] leftMoney = postorder(root.left);
int[] rightMoney = postorder(root.right);
int[] money = new int[2];
money[0] = Math.max(leftMoney[0], leftMoney[1]) + Math.max(rightMoney[0], rightMoney[1]);
money[1] = (leftMoney[0] + rightMoney[0]) + root.val;
return money;
}
}