題目:
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為「根」。 除了「根」之外,每棟房子有且只有乙個「父「房子與之相連。一番偵察之後,聰明的小偷意識到「這個地方的所有房屋的排列類似於一棵二叉樹」。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
示例 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)表示選擇 o 節點的情況下,o節點的子樹上被選擇的節點的最大權值和;g(o) 表示不選擇 o節點的情況下,o 節點的子樹上被選擇的節點的最大權值和;l 和 r代表 o 的左右孩子。
當 o 被選中時,o 的左右孩子都不能被選中,故 o 被選中情況下子樹上被選中點的最大權值和為 l和 r不被選中的最大權值和相加,即 f(o)=g(l)+g(r)
當 o 不被選中時,o 的左右孩子可以被選中,也可以不被選中。對於 o 的某個具體的孩子 x,它對 o的貢獻是 x被選中和不被選中情況下權值和的較大值。故 g(o)=max+max
簡而言之,就是當該點被選中時,他的總值等於左右兩棵子樹不被選中的值加上該節點的值。而當這點不被選中時,他的總值等於左右子樹被選中和不被選中的最大值之和。
func max(a,b int) intreturn b
}func rob(root *treenode) int
func dfs2(root *treenode)int
} l:=dfs2(root.left) //先遍歷到底層逐層向上更新
r:=dfs2(root.right)
selected:= root.val + l[1] + r[1] //如果該點被選中,則他等於自己的值加上左右子樹不被選中的值
notselected := max(l[1],l[0]) +max(r[1],r[0]) //如果該點未被選中,則他等於左子樹被選中或不被選中的最大值加上右子樹被選中或不被選中的最大值之和
return int //返回該點被選中和不被選中所能提供的值
}
《LeetCode筆記39》 打家劫舍
你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。示例 1 輸入 1...
198 打家劫舍
很明顯是dp問題。用乙個一維陣列表示dp陣列,狀態轉移方程為 resmax index max nums index resmax index 2 resmax index 1 其中resmax儲存,遍歷到該節點時的,最大值。注意,遍歷到該節點,但該節點不一定選。另外該題的初始解要想清楚。即resm...
198 打家劫舍
你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。示例 1 輸入 1...