337.打家劫舍Ⅲ

难度:中等
题目描述:
思路总结
刚开始想到了二叉树的层次遍历,其实这题可以用层次遍历+DP解决。然后看答案树形DP,初始解法一+后续两种优化。
题解一:(超时)
其实还是递归层数的问题,加个lru_cache()装饰器就好了。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def rob(self, root: TreeNode) -> int:
        #思路:爷爷+孙子 vs. 儿子
        if not root:return 0
        money = root.val
        if root.left:
            money += self.rob(root.left.left) + self.rob(root.left.right)
        if root.right:
            money += self.rob(root.right.left) + self.rob(root.right.right)
        return max(money, self.rob(root.left)+self.rob(root.right))

题解一结果:
我佛,人家Java都不超时。
337.打家劫舍Ⅲ_第1张图片
加了lru_cache()之后的结果:
337.打家劫舍Ⅲ_第2张图片
题解二:
爷爷+孙子和爸爸,两下计算下来,必然是有一大部分是重叠计算,因此我们可以用记忆法进行优化,搞一个dict存储每个结点的最大偷钱数。
note:这里不能用lru_cache()进行优化了,因为函数中有不能hashable的参数。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
import functools
class Solution:
    # @functools.lru_cache(None)
    def rob(self, root: TreeNode) -> int:
        #思路:爷爷+孙子 vs. 儿子
        memo = {}
        def robWhat(root, memo):
            if not root:return 0
            if root in memo.keys():
                return memo[root]
            money = root.val
            if root.left:
                money += robWhat(root.left.left, memo) + robWhat(root.left.right, memo)
            if root.right:
                money += robWhat(root.right.left, memo) + robWhat(root.right.right, memo)
            res = max(money, robWhat(root.left, memo)+robWhat(root.right, memo))
            memo[root] = res
            return res
        return robWhat(root, memo)
        

题解二结果:
看来上面的判断还是有误,使用记忆法以后我们可以得到不错的结果。由此可见,上面原始代码的问题是递归次数过多导致的导致运算过慢。(而不是层级过多)
337.打家劫舍Ⅲ_第3张图片
题解三:
我们可以转变一个思路。对于每个节点来说,就是偷或者不偷,如果偷,存左右子节点选择不偷加当前结点值;如果不偷,存左右子节点选择偷最大值相加。
实现其实也很简单。就是每次迭代时迭代计算左右孩子的(不偷,偷)的最大值,然后返回当前结点的(不偷,偷)的最大值,每次返回元组。(不偷:选左子节点偷/不偷的最大值,右同理;偷:选左右子节点不偷值+当前结点值)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
import functools
class Solution:
    
    def rob(self, root: TreeNode) -> int:
        
        def robWhat(node):
            if not node:return (0, 0)
            left = robWhat(node.left)
            right = robWhat(node.right)
            return (max(left[0], left[1])+max(right[0], right[1]), left[0]+right[0]+node.val)   
        return max(robWhat(root))

题解三结果:
337.打家劫舍Ⅲ_第4张图片
加了functools.lru_cache()后的结果:
337.打家劫舍Ⅲ_第5张图片

你可能感兴趣的:(朱滕威的面试之路)