2020.8.5 力扣每日
1 class Solution { 2 public int rob(TreeNode root) { 3 int[] rootStatus = dfs(root); //存取两种方案结果 4 return Math.max(rootStatus[0], rootStatus[1]); 5 } 6 7 public int[] dfs(TreeNode node) { 8 if (node == null) { //空值返回 9 return new int[]{0, 0}; 10 } 11 int[] l = dfs(node.left); //左子树 12 int[] r = dfs(node.right); //右子树 13 int selected = node.val + l[1] + r[1]; //选择根节点 14 int notSelected = Math.max(l[0], l[1]) + Math.max(r[0], r[1]); //不选择根节点 15 return new int[]{selected, notSelected}; 16 } 17 }
解题思路:
第一眼看题还以为只需要层次遍历,按层比较下就好,结果发现对于[2,1,3,null,4]时结果就出错了。所以重新审题,发现还是有一定规律的。对于任意一个结点node来说,如果打劫了该节点,那么接下来势必不能打劫左节点与右节点,只能打劫两者的子节点;而未打劫的话,那么就可以打劫左节点和右节点,也可以打劫两者的子节点。因为对于所有节点都是这样的。那么我们完全可以利用递归来进行计算。利用一个大小为2的数组来存储两种情况。
注意点:
- 由于对于任意一个节点的状态,我们都需要先得知其左右子树的状态,所以实际上是一个后序遍历的算法,计算状态需在遍历之后。
- 对于未选择根节点的状态,需注意,仍然可以不选择左右节点,选择其子节点,所以需判断两种选择的大小,则判断对于左节点来说,选择左节点与不选择左节点的l[1],l[0]的大小,r[0]与r[1]的大小
时间复杂度:O(N),N为二叉树节点数
空间复杂度:O(N)