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)

posted @ 2020-08-06 22:46  小小码农-安  阅读(144)  评论(0编辑  收藏  举报