Leetcode每日一题——337. 打家劫舍 III。递归四部曲,动态规划

题目链接:

力扣

题目描述:

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。

Leetcode每日一题——337. 打家劫舍 III。递归四部曲,动态规划_第1张图片

提示:

树的节点数在 [1, 104] 范围内
0 <= Node.val <= 104

解题思路:

二叉树一般用递归,从题目看,父节点偷不偷还取决于子节点和孙子结点的情况,感觉可以把父节点的求解分解成子节点和孙子结点的情况,这就和动态规划的思路接近了。所以这道题可以看成是树+动态规划的结合

        递归四部曲:

        确定递归函数的作用:求出考虑偷这个结点所得的最大金额

        确定递归参数和返回值:参数是要偷的结点,返回值是一个列表,对应着偷这个结点和不偷这个结点各自对应的最大金额

        终止条件:结点为空时,返回(0,0)

        单层逻辑:后序遍历,因为要用到递归的返回值做判断。先得到考虑偷左右孩子结点的情况,再根据偷不偷本结点来分类:偷本结点则取不偷左右孩子结点的数值,不偷本结点则左右孩子可偷可不偷,取最大值就好了。最终返回本结点的偷盗情况(偷的情况,不偷的情况)

代码如下:

# 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 rob1(self, root: TreeNode):
        if root is None: return (0, 0)#终止条件
        left = self.rob1(root.left)#考虑偷左孩子结点的情况
        right = self.rob1(root.right)#考虑偷右孩子结点的情况
        val1 = left[1] + right[1] + root.val#偷本结点
        val2 = max(left) + max(right)#不偷本结点
        return (val1, val2)

    def rob(self, root: TreeNode) -> int:
        return max(self.rob1(root))

你可能感兴趣的:(动态规划,递归,leetcode,动态规划,算法,python)