小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/house-robber-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1. 暴力遍历所有情况 [超时]
对每一个节点都可以选择偷与不偷
对比偷与不偷的结果选择大者作为返回
注意剔除不能选择偷的情况
class Solution:
def rob(self, root: TreeNode):
reject_nodes = {}
def deep(root):
if root is None:
return 0
nonlocal reject_nodes
if reject_nodes.get(root) is None:
reject_nodes[root.left] = 1
reject_nodes[root.right] = 1
l1 = deep(root.left) + deep(root.right) + root.val
reject_nodes[root.left] = None
reject_nodes[root.right] = None
l2 = deep(root.left) + deep(root.right)
return max(l1, l2)
else:
return deep(root.left) + deep(root.right)
return deep(root)
2. 优化
对于1中的逻辑 可以发现有很多重复计算 简单改造下代码缓存计算的结果
class Solution:
def rob(self, root: TreeNode):
can_rob_cache = {}
not_rob_cache = {}
# canRob 代表当前节点可以偷
def deep(root, canRob):
if root is None:
return 0
nonlocal can_rob_cache
nonlocal not_rob_cache
if canRob:
if can_rob_cache.get(root) is not None:
return can_rob_cache.get(root)
l1 = deep(root.left, False) + deep(root.right, False) + root.val
l2 = deep(root.left, True) + deep(root.right, True)
res = max(l1, l2)
can_rob_cache[root] = res
return res
else:
if not_rob_cache.get(root) is not None:
return not_rob_cache.get(root)
res = deep(root.left, True) + deep(root.right, True)
not_rob_cache[root] = res
return res
return deep(root, True)
可以通过