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

337. 打家劫舍 III

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

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

示例 1:

輸入: [3,2,3,null,3,null,1]

3
/ \
2 3
\ \
3 1

輸出: 7
解釋:小偷一晚能夠盜取的最高金額 = 3 + 3 + 1 = 7.
示例 2:

輸入: [3,4,5,1,3,null,1]

3
/ \
4 5
/ \ \
1 3 1

輸出: 9
解釋:小偷一晚能夠盜取的最高金額= 4 + 5 = 9.

思路:

  • 對於一個節點 root,因為不能搶劫相鄰的父子節點,所以,可以分為2種情況;
  • 第一種:搶劫當前節點,不搶劫其兒子節點,要搶劫孫子節點;
  • 第二種:不搶劫當前節點,搶劫其兒子節點;
  • 比較上面 兩種情況,將最大的值,存入雜湊字典中,防止遞迴中重複計算。

class Solution {
    Map<TreeNode, Integer> map = new HashMap<>(); //
全域性的雜湊字典 public int rob(TreeNode root) { if(root == null) return 0; if(map.containsKey(root)) return map.get(root); //若已經存在,直接返回雜湊結果 int do_it = root.val + (root.left == null ? 0 : rob(root.left.left) + rob(root.left.right)) + (root.right == null ? 0 : rob(root.right.left) + rob(root.right.right));
//搶劫當前節點及其孫子節點,不搶劫其兒子節點 int not_do = rob(root.left) + rob(root.right); //不搶劫當前節點,則搶劫其左右子節點 int max = Math.max(do_it, not_do); //比較當前節點搶劫與否中,誰更大 map.put(root, max); //將獲得的最大金額,存入雜湊字典 return max; } }