1. 程式人生 > 實用技巧 >LeetCode-337-打家劫舍III

LeetCode-337-打家劫舍III

題目

在上次打劫完一條街道之後和一圈房屋後,小偷又發現了一個新的可行竊的地區。這個地區只有一個入口,我們稱之為“根”。 除了“根”之外,每棟房子有且只有一個“父“房子與之相連。一番偵察之後,聰明的小偷意識到“這個地方的所有房屋的排列類似於一棵二叉樹”。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。

計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。

示例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 ) return
0; 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 }