1. 题目:
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
示例 1:
输入: root = [3,2,3,null,3,null,1]
输出: 7
解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
示例 2:
输入: root = [3,4,5,1,3,null,1]
输出: 9
解释: 小偷一晚能够盗取的最高金额 4 + 5 = 9
2. 我的代码:
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def rob(self, root: Optional[TreeNode]) -> int: # 后序遍历 def rob_tree(node): # 终止条件 if node == None: return 0, 0 left_dp_rob, left_dp_norob = rob_tree(node.left) right_dp_rob, right_dp_norob = rob_tree(node.right) # 递推公式 dp_rob = left_dp_norob + right_dp_norob + node.val dp_norob = max(left_dp_rob, left_dp_norob) + max(right_dp_rob, right_dp_norob) return dp_rob, dp_norob return max(rob_tree(root))
这里是个二叉树结构的打家劫舍,题目详细就不多说了,类似于之前的线性结构与环形结构,本质不变,都是相邻的房间不能偷。
为了能够将结果汇集起来,我们继续使用二叉树遍历中的后序遍历。
这里,递归函数返回2个值,一个是偷这个节点时的最大金币、另一个时不偷这个节点时的最大金币。因此,我们获取左右子节点返回的偷和不偷的情况: left_dp_rob, left_dp_norob = rob_tree(node.left)
和right_dp_rob, right_dp_norob = rob_tree(node.right)
。然后递推公式:偷当前节点时的最大金币就是左不偷 + 右不偷 + 本节点:dp_rob = left_dp_norob + right_dp_norob + node.val
。不偷当前节点时的最大金币就是左边的偷与不偷的最大值 + 右边的偷与不偷的最大值dp_norob = max(left_dp_rob, left_dp_norob) + max(right_dp_rob, right_dp_norob)