337 打家劫舍 III python3

2021-09-27 12:09:54 字數 4424 閱讀 4382

在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為「根」。除了「根」之外,每棟房子有且只有乙個「父」房子與之相連。一番偵察之後,聰明的小偷意識到「這個地方的所有房屋的排列類似於一棵二叉樹」。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。

計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。

示例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

# -*- coding: utf-8 -*-

# definition for a binary tree node.

# class treenode:

# def __init__(self, x):

# self.val = x

# self.left = none

# self.right = none

class

solution()

:"""給出打家劫舍iii的答案"""

defmoney_rob_or_norob

(self, root)

:"""

給出偷當前節點和不偷當前節點,分別能得到的最大金額

例如,對於根節點的左右孩子節點

分別定義元組my_left和my_right,其中:

[0]:表示如果偷當前節點,可以得到的最大金額

[1]:表示如果不偷當前節點,可以得到的最大金額

則最終的最大金額為以下5個數值中的最大值

偷根節點

1. 不偷左右孩子:root.val + m_l[1] + m_r[1]

不偷根節點

2. 偷左,偷右:m_l[0] + m_r[0]

3. 偷左,不偷右:m_l[0] + m_r[1]

4. 不偷左,偷右:m_l[1] + m_r[0]

5. 不偷左,不偷右:m_l[1] + m_r[1]

以此類推。。。

"""# 若root為空,返回0

if root is

none

:return(0

,0) my_left = self.money_rob_or_norob(root.left)

my_right = self.money_rob_or_norob(root.right)

rob_current = root.val + my_left[1]

+ my_right[1]

norob_current =

max(

max(my_left[0]

+ my_right[0]

, my_left[0]

+ my_right[1]

),max(my_left[1]

+ my_right[0]

, my_left[1]

+ my_right[1]

))return

(rob_current, norob_current)

defrob

(self, root)

:"""

給出能偷取的最大金額

:type root: treenode

:rtype: int

"""return

max(self.money_rob_or_norob(root)

)

# -*- coding: utf-8 -*-

import unittest

from house_robber_iii import solution

class

treenode()

:"""表示二叉樹的類"""

def__init__

(self, x)

: self.val = x

self.left =

none

self.right =

none

class

testasteroidcollision

(unittest.testcase)

:"""針對solution類的測試"""

defsetup

(self)

:"""建立乙個solution類,供使用的測試方法使用"""

self.my_solution = solution(

)def

test_empty_tree

(self)

:"""空樹"""

root =

none

result = self.my_solution.rob(root)

expected_result =

0 self.assertequal(result, expected_result)

deftest_only_one_node_value_0

(self)

:"""

只有乙個根節點

而且根節點為0

"""root = treenode(0)

result = self.my_solution.rob(root)

expected_result =

0 self.assertequal(result, expected_result)

deftest_only_one_node_value_1

(self)

:"""

只有乙個根節點

而且根節點為1

"""root = treenode(1)

result = self.my_solution.rob(root)

expected_result =

1 self.assertequal(result, expected_result)

deftest_rob_root_norob_son

(self)

:"""

偷根節點

不偷左右孩子

"""root = treenode(10)

root.left = treenode(3)

root.right = treenode(4)

result = self.my_solution.rob(root)

expected_result =

10 self.assertequal(result, expected_result)

deftest_rob_root_rob_grandson

(self)

:"""

偷根節點

偷孫節點

"""root = treenode(2)

root.left = treenode(3)

root.right = treenode(4)

root.left.left = treenode(2)

root.right.right = treenode(4)

result = self.my_solution.rob(root)

expected_result =

8 self.assertequal(result, expected_result)

deftest_rob_left_norob_right_rob_rightson

(self)

:"""

偷左孩子

不偷右孩子,但是偷右孩子的孩子

"""root = treenode(1)

root.left = treenode(10)

root.right = treenode(2)

root.left.left = treenode(3)

root.left.right = treenode(4)

root.right.left = treenode(7)

root.right.right = treenode(8)

result = self.my_solution.rob(root)

expected_result =

25 self.assertequal(result, expected_result)

unittest.main(

)

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 打家劫舍3

在上次打劫完一條街道之後和一圈房屋後,小偷又發現了乙個新的可行竊的地區。這個地區只有乙個入口,我們稱之為 根 除了 根 之外,每棟房子有且只有乙個 父 房子與之相連。一番偵察之後,聰明的小偷意識到 這個地方的所有房屋的排列類似於一棵二叉樹 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。計...