在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為「根」。 除了「根」之外,每棟房子有且只有乙個「父「房子與之相連。一番偵察之後,聰明的小偷意識到「這個地方的所有房屋的排列類似於一棵二叉樹」。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
由於房屋是樹狀的,因此,我們可以使用遍歷樹的傳統方法進行遍歷(前序、中序、後續)
簡單的思路是,從樹低進行往上遍歷,拿到最優的打劫值。可以選用後續遍歷
得到每一節點的最優值,最後選取最優的結果
1.dp[i]代表該節點及以下拿到的最多的錢
2.動態方程:
3.初始化:當前樹的形狀為空的時候,直接返回dp[0, 0]
# definition for a binary tree node.
class treenode(object):
def __init__(self, x):
self.val = x
self.left = none
self.right = none
class solution(object):
def rob(self, root):
""":type root: treenode
:rtype: int
"""def posttrasval(root): # 從樹低進行往上遍歷,拿到最優的打劫值。可以選用後續遍歷
dp = [0, 0] # dp[i]代表該節點及以下拿到的最多的錢
if not root:
return dp
left = posttrasval(root.left)
right = posttrasval(root.right)
# dp[0]代表不偷該節點拿到最多的錢,則兒子節點偷不偷都ok。
dp[0] = max(left[0], left[1]) + max(right[0], right[1])
# dp[1]代表偷了該節點拿到最多的錢,則兒子節點都不能被偷。
dp[1] = root.val + left[0] + right[0]
return dp
dp = posttrasval(root)
return max(dp[0], dp[1])
if __name__ == '__main__':
t = treenode(3)
t.left = treenode(2)
t.right = treenode(3)
t.left.right = treenode(3)
t.right.right = treenode(1)
s = solution()
print(s.rob(t))
DP LeetCode198 打家劫舍
你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。1.dp i 代表...
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...