打家劫舍III 多解法

打家劫舍 III

在这里插入图片描述

记忆化递归,后续遍历,单个状态转移

一开始想不出什么好的方法,就用了dfs+剪枝的方法,采用后续遍历的方式,每个节点返回这棵子树能获得的最大金额。
最大金额分两种情况,当前节点偷和当前节点不偷
在这里插入图片描述

# 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:
        dict1 = {}
        def _dfs(root):
            if root == None:
                return 0
            value1 = 0
            value2 = 0
            for item in (root.left, root.right):# 遍历两个孩子节点
                if not item :
                    dict1[item] = 0
                    continue
                if item in dict1.keys():
                    tempValue = dict1[item]
                else: tempValue = _dfs(item); dict1[item] = tempValue
                value1 += tempValue
                
                for child in (item.left, item.right):# 遍历4个孙子节点
                    tempValue = _dfs(child)
                    if child in dict1.keys():
                        tempValue = dict1[child]
                    else: tempValue = _dfs(child); dict1[child] = tempValue
                    value2 += tempValue
            maxValue = max(value1, value2 + root.val)
            dict1[root] = maxValue
            return maxValue
        return _dfs(root)

在这里插入图片描述

上面的记忆化递归过于难看,用字典来保存状态只需要在递归函数的首尾即可,下面的更清晰

# 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:
        dict1 = {}
        def _dfs(root):
            if root == None:
                return 0
            if root in dict1.keys(): # 判断字典中是否已经包含
                return dict1[root] # 直接返回对应的状态
            value1 = 0
            value2 = 0
            for item in (root.left, root.right):# 遍历两个孩子节点
                if not item :
                    dict1[item] = 0
                    continue
                tempValue = _dfs(item); 
                value1 += tempValue
                for child in (item.left, item.right): # 遍历4个孙子节点
                    tempValue = _dfs(child)
                    value2 += tempValue
            maxValue = max(value1, value2 + root.val)
            dict1[root] = maxValue # 记忆当前节点的状态
            return maxValue
        return _dfs(root)

后续遍历,dfs, 两个状态转移,字典,lambda

在这里插入图片描述
这里为了处理None节点与字典对None节点的初始化,使用defaultdict(lambda : 0) , 对于新增键值,字典的返回结果为0, defaultdict()只能传入不带参数的函数,或者None值。这里使用了lambda表达式。

# 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:
        dict0 = defaultdict(lambda : 0)
        dict1 = defaultdict(lambda : 0)
        def _dfs(root):
            if not root:
                return 0
            _dfs(root.left)
            _dfs(root.right)
            dict0[root] = max(dict0[root.left], dict1[root.left]) + max(dict0[root.right], dict1[root.right])
            dict1[root] = dict0[root.left] + dict0[root.right] + root.val
        _dfs(root)
        return max(dict0[root], dict1[root])

对于上面的代码可以简化一下

因为涉及到的状态只和孩子节点有关,状态可以通过孩子节点返回。就省了字典的开销了。
在这里插入图片描述

# 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:
        def _dfs(root):
            if not root:
                return (0,0)
            lvalue = _dfs(root.left)
            rvalue = _dfs(root.right)
            noselected = max(lvalue[0], lvalue[1]) + max(rvalue[0], rvalue[1])
            selected = lvalue[0]+rvalue[0] + root.val
            return (noselected, selected)
        res = _dfs(root)
        return max(res[0], res[1])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值