先看递归的解法
无非就是取recur(root) + recur(root孙子节点)… 和 recur(root.left) + recur(root.right)的最大值
但是递归会反复求解之前求过的值,比如求recur(root.left)时又会重新求一遍recur(root孙子节点)
这个时候就可以利用dp的思想,备忘录方法,用一个HashMap<TreeNode, Integer>记录之前求过的节点。
class Solution { private HashMap<TreeNode, Integer> hash = new HashMap<>(); public int rob(TreeNode root) { if(root == null) return 0; if(hash.containsKey(root)) return hash.get(root); if(root.left == null && root.right == null){ hash.put(root, root.val); return root.val; } if(root.left == null){ int res = Math.max(root.val + rob(root.right.left) + rob(root.right.right), rob(root.right)); hash.put(root, res); return res; } if(root.right == null){ int res = Math.max(root.val + rob(root.left.left) + rob(root.left.right), rob(root.left)); hash.put(root, res); return res; } int res = Math.max(root.val + rob(root.left.left) + rob(root.left.right) + rob(root.right.left) + rob(root.right.right), rob(root.left) + rob(root.right)); hash.put(root, res); return res; } }
还有没有更好的解法呢?
有,连这个hashmap也可以去掉
我们可以把dp[]改成2维,[0] 记录不rob当前节点的最大获利,[1]记录rob当前节点的最大获利。
class Solution { public int rob(TreeNode root) { if(root == null) return 0; int[] dp = new int[2]; dp = helper(root); return Math.max(dp[0], dp[1]); } private int[] helper(TreeNode root){ if(root == null) return new int[2]; int[] res = new int[2]; int[] left = helper(root.left); int[] right = helper(root.right); res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); res[1] = left[0] + right[0] + root.val; return res; } }