LeetCode-337-打家劫舍III
阿新 • • 發佈:2020-08-05
題目
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了一個新的可行竊的地區。這個地區只有一個入口,我們稱之為“根”。 除了“根”之外,每棟房子有且只有一個“父“房子與之相連。一番偵察之後,聰明的小偷意識到“這個地方的所有房屋的排列類似於一棵二叉樹”。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
示例1: 輸入: [3,2,3,null,3,null,1] 3 / \ 2 3 \ \3 1 輸出: 7 解釋:小偷一晚能夠盜取的最高金額 = 3 + 3 + 1 = 7.
思路
根據題目,偷了爺爺節點,則不能去偷兩個父節點,但是可以去偷四個孫節點;不偷爺爺節點,則可以偷兩個父節點。
所以金額最大則是
爺爺節點金額 + 四個孫節點的金額 vs. 兩個父節點的金額
使用動態規劃,且狀態轉移方程:maxValue = Max(root + root.left.left + root.left.right + root.right.left + root.right.right , root.left + root.right )
使用一個hashmap進行記憶化,記憶當前節點的最大金額
1 public int rob(TreeNode root) { 2 HashMap<TreeNode, Integer> memo = new HashMap<>(); 3 return robInternal(root, memo); 4 } 5 6 public int robInternal(TreeNode root, HashMap<TreeNode, Integer> memo) { 7 8 if(root == null ) return0; 9 if(memo.containsKey(root)) return memo.get(root); 10 11 int money = root.val; 12 13 // 加上左子樹兩個孫節點的金額 14 if(root.left != null ) { 15 16 money += robInternal(root.left.left,memo) + robInternal(root.left.right,memo); 17 } 18 19 // 加上右子樹兩個孫節點的金額 20 if(root.right != null ) { 21 22 money += robInternal(root.right.left,memo) + robInternal(root.right.right,memo); 23 } 24 25 // 對比兩種方式的較大值 26 int result = Math.max(money, robInternal(root.left, memo)+robInternal(root.right, memo)); 27 28 // 將較大值和節點存入hashmap實現記憶化 29 memo.put(root,result); 30 31 return result; 32 }