在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為「根」。
除了「根」之外,每棟房子有且只有乙個「父「房子與之相連。一番偵察之後,聰明的小偷意識到「這個地方的所有房屋的排列類似於一棵二叉樹」。
如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
示例 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.
使用爺爺、兩個孩子、4 個孫子來說明問題
首先來定義這個問題的狀態
爺爺節點獲取到最大的偷取的錢數呢
首先要明確相鄰的節點不能偷,也就是爺爺選擇偷,兒子就不能偷了,但是孫子可以偷
二叉樹只有左右兩個孩子,乙個爺爺最多 2 個兒子,4 個孫子
根據以上條件,我們可以得出單個節點的錢該怎麼算
4 個孫子偷的錢 + 爺爺的錢 vs 兩個兒子偷的錢哪個組合錢多,就當做當前節點能偷的最大錢數。這就是動態規劃裡面的最優子結構
class solution
}
class solution
private int robinternal(treenode root,hashmapmemo)
if(root.right != null)
int result = math.max(money,robinternal(root.left,memo)+ robinternal(root.right,memo));
memo.put(root,result);
return result;
}}
/*
思路改進:
我們換一種辦法來定義此問題
每個節點可選擇偷或者不偷兩種狀態,根據題目意思,相連節點不能一起偷
當前節點擊擇偷時,那麼兩個孩子節點就不能選擇偷了
當前節點擊擇不偷時,兩個孩子節點只需要拿最多的錢出來
就行(兩個孩子節點偷不偷沒關係)
我們使用乙個大小為 2 的陣列來表示
int res = new int[2] 0 代表不偷,1 代表偷
任何乙個節點能偷到的最大錢的狀態可以定義為
當前節點擊擇不偷:
當前節點能偷到的最大錢數 = 左孩子能偷到的錢 + 右孩子能偷到的錢
當前節點擊擇偷:
當前節點能偷到的最大錢數 = 左孩子選擇自己不偷時能得到的錢 +
右孩子選擇不偷時能得到的錢 +
當前節點的錢數
*/public int rob(treenode root)
public int robinternal(treenode root)
LeetCode337 打家劫舍
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為 根 除了 根 之外,每棟房子有且只有乙個 父 房子與之相連。一番偵察之後,聰明的小偷意識到 這個地方的所有房屋的排列類似於一棵二叉樹 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。計...
leetcode337打家劫舍III
不搶劫該節點,則可以搶劫該節點的左右字節點 注意,node節點不搶不意味著一定要搶它的左右子結點,所以在方法中應該呼叫rob方法,而不是robinclude方法 public int robexclude treenode node return rob node.left rob node.rig...
Leetcode 337 打家劫舍 III
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為 根 除了 根 之外,每棟房子有且只有乙個 父 房子與之相連。一番偵察之後,聰明的小偷意識到 這個地方的所有房屋的排列類似於一棵二叉樹 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。計...