337. 打家劫舍 III
https://leetcode-cn.com/problems/house-robber-iii/
一:前序遍历
1、直接遍历:超时
class Solution:
def rob(self, root: TreeNode) -> int:
if root==None:
return 0
#抢root,然后去下下家
if root.left == None and root.right == None: #左右都为空
do = root.val
elif root.left == None: #只有左边为空
do = root.val + self.rob(root.right.left) + self.rob(root.right.right)
elif root.right == None: # 只有右边为空
do = root.val + self.rob(root.left.left) + self.rob(root.left.right)
else: #都不为空
do = root.val + self.rob(root.left.left) + self.rob(root.left.right) + self.rob(root.right.left) + self.rob(root.right.right)
#不抢,然后去下家
not_do = self.rob(root.left) + self.rob(root.right)
res =max(do, not_do)
return res
2、使用备忘录
在1中打印每次的do和not_do以及节点序号,发现存在很多重复访问,当每个节点的遍历走到res时,已经计算完毕,之后再次计算也是同样的结果,因此用一个备忘录保存,避免重复计算
class Solution:
memo = {} #全局备忘录
def rob(self, root: TreeNode) -> int:
if root==None:
return 0
if root in self.memo: #该节点已有结果,直接返回
return self.memo[root]
#抢root,然后去下下家
if root.left == None and root.right == None: #左右都为空
do = root.val
elif root.left == None: #只有左边为空
do = root.val + self.rob(root.right.left) + self.rob(root.right.right)
elif root.right == None: # 只有右边为空
do = root.val + self.rob(root.left.left) + self.rob(root.left.right)
else: #都不为空
do = root.val + self.rob(root.left.left) + self.rob(root.left.right) + self.rob(root.right.left) + self.rob(root.right.right)
#不抢,然后去下家
not_do = self.rob(root.left) + self.rob(root.right)
res =max(do, not_do)
self.memo[root] = res #记入备忘录
return res
最后更新于