題目地址:
https://leetcode-cn.com/probl...
題目描述:
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了一個新的可行竊的地區。這個地區只有一個入口,我們稱之爲“根”。 除了“根”之外,每棟房子有且只有一個“父“房子與之相連。一番偵察之後,聰明的小偷意識到“這個地方的所有房屋的排列類似於一棵二叉樹”。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
示例 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.val+左子樹的左右子樹偷盜最大值+右子樹的左右子樹偷盜最大值。
若不偷根節點,則偷盜數額等於左子樹的偷盜最大值+右子樹的偷盜最大值。
java ac代碼:
/**
- Definition for a binary tree node.
- public class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
- TreeNode(int x) { val = x; }
- }
*/
class Solution {
public int rob(TreeNode root) {
//若偷根,則只能偷左右子樹的左右子樹
//若不偷根,則左右子樹都可以偷
//比較兩者誰大
if(root == null)return 0;
int temp = root.val;
if(root.left != null)temp += rob(root.left.left)+rob(root.left.right);
if(root.right != null)temp += rob(root.right.left)+rob(root.right.right);
return Math.max(temp,rob(root.left)+rob(root.right));
}
}
不過這樣的複雜度過大,因爲有很多步驟被重複計算。
添加一個HashMap記錄已經存在的結果,這樣避免重複計算。
java ac代碼:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
HashMap<TreeNode,Integer>map = new HashMap(1000);
public int rob(TreeNode root) {
//若偷根,則只能偷左右子樹的左右子樹
//若不偷根,則左右子樹都可以偷
//比較兩者誰大
if(root == null)return 0;
if(map.containsKey(root))return map.get(root);
int temp = root.val;
if(root.left != null)temp += rob(root.left.left)+rob(root.left.right);
if(root.right != null)temp += rob(root.right.left)+rob(root.right.right);
int ans = Math.max(temp,rob(root.left)+rob(root.right));
map.put(root,ans);
return ans;
}
}
這樣一來,速度快了很多,不過需要注意的是一般Map的key是類類型,需要重寫hashCode和equals方法。這裏雖然沒寫,但是有可能是沒有產生hash衝突,或者是後臺已經幫我們謝過了。