在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為「根」。 除了「根」之外,每棟房子有且只有乙個「父「房子與之相連。一番偵察之後,聰明的小偷意識到「這個地方的所有房屋的排列類似於一棵二叉樹」。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
示例 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.
/* 簡化一下這個問題:一棵二叉樹,樹上的每個點都有對應的權值,每個點有兩種狀態(選中和不選中),問在不能同時選中有父子關係的點的情況下,能選中的點的最大權值和是多少。
我們可以用 f(o)f(o) 表示選擇 oo 節點的情況下,oo 節點的子樹上被選擇的節點的最大權值和;g(o)g(o) 表示不選擇 oo 節點的情況下,oo 節點的子樹上被選擇的節點的最大權值和;ll 和 rr 代表 oo 的左右孩子。
當 oo 被選中時,oo 的左右孩子都不能被選中,故 oo 被選中情況下子樹上被選中點的最大權值和為 ll 和 rr 不被選中的最大權值和相加,即 f(o) = g(l) + g(r)f(o)=g(l)+g(r)。
當 oo 不被選中時,oo 的左右孩子可以被選中,也可以不被選中。對於 oo 的某個具體的孩子 xx,它對 oo 的貢獻是 xx 被選中和不被選中情況下權值和的較大值。故 g(o) = \max \+\max\g(o)=max+max。
*/struct subtreestatus
;class
solution;}
auto l =
dfs(o-
>left)
;auto r =
dfs(o-
>right)
;int selected = o-
>val + l.notselected + r.notselected;
int notselected =
max(l.selected, l.notselected)
+max
(r.selected, r.notselected)
;return;}
introb
(treenode* o)
};
337 打家劫舍 III
思路 這是乙個典型的樹形dp問題,對每乙個節點都有兩種選擇 選他或者不選他。選他的話,那麼就不能選擇它的父節點 兄弟節點和子節點 不選這個節點,那麼就可以選擇該節點的左右子樹 選最大的 建立乙個dp表,令dp 0 表示選,dp 1 表示不選。class solution object def rob...
337 打家劫舍 III
方法一 遞迴 超時!class solution 方法二 用雜湊表改進解決重複子問題,超時!class solution return res public int rob treenode root 方法三 用乙個pair分別記錄包含根節點和不包含根節點時的最大值 class solution a...
337 打家劫舍 III
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為 根 除了 根 之外,每棟房子有且只有乙個 父 房子與之相連。一番偵察之後,聰明的小偷意識到 這個地方的所有房屋的排列類似於一棵二叉樹 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。計...