前言
对于树问题,存在 前序与DFS/中序与平衡二叉树/后序与回溯/层序与BFS。对于打家劫舍,是一道经典的动态规划问题,当线性的数组转变成了分支的树结构,状态又该如何从两条分支去转移?
可以配合回溯,得到左右孩子两条分支的节点存钱情况,在根据实际需求,进行存钱选取。
一、打家劫舍III
状态转移没细细思考时,碰到的树结构。
二、回溯+动态规划
package everyday.tree;
public class Rob {
// 利用回溯来配合动态规划。
public int rob(TreeNode root) {
int[] r = order(root);
return Math.max(r[0], r[1]);
}
private int[] order(TreeNode root) {
if (null == root) return new int[]{0, 0};
int[] l = order(root.left);
int[] r = order(root.right);
// 选根,就只能选择比较深的节点所存到的钱。
int first = root.val + l[0] + r[0];
// 不选根,这就值得考虑,在根的左孩子和更下一层就可以随便选一个,毕竟不会挨着根,右边同理。
int second = Math.max(l[0], l[1]) + Math.max(r[0], r[1]);
return new int[]{second, first};
/*
二叉树问题:
前序遍历与DFS;中序遍历与平衡二叉树;后序遍历与回溯;层序遍历与BFS;
*/
}
// 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;
}
}
}
总结
1)树问题的基础,莫过于,前序与DFS/中序与平衡二叉/后序与回溯/层序与BFS。
2)动态规划的状态转移,是需要值得细细思考的地方。
参考文献
[1] LeetCode 打家劫舍